ti外包网站建设wordpress 插件 支付

news/2025/9/24 4:29:53/文章来源:
ti外包网站建设,wordpress 插件 支付,青海城乡建设部网站,网站建设功能选择表背景 最近在研究tomcat调优的问题#xff0c;开发人员做过的最多的tomcat调优想必就是线程池调优了#xff0c;但是tomcat并没有使用jdk自己的线程池实现#xff0c;而是自定了了线程池#xff0c;自己实现了ThreadPoolExecutor类位于org.apache.tomcat.util.threads包下 …背景 最近在研究tomcat调优的问题开发人员做过的最多的tomcat调优想必就是线程池调优了但是tomcat并没有使用jdk自己的线程池实现而是自定了了线程池自己实现了ThreadPoolExecutor类位于org.apache.tomcat.util.threads包下 jdk线程池 首先回顾一下jdk的线程池实现 提交一个任务时 1 如果此时线程池中的数量小于corePoolSize无论线程池中的线程是否处于空闲状态都会创建新的线程来处理被添加的任务。 2 如果此时线程池中的数量大于等于于corePoolSize但是缓冲队列workQueue未满那么任务被放入缓冲队列。 3 如果此时线程池中的数量大于等于corePoolSize且缓冲队列workQueue满但是线程池中的数量小于maximumPoolSize则建新线程来处理被添加的任务。 4 如果此时线程池中的数量大于corePoolSize且缓冲队列workQueue满并且线程池中的数量等于maximumPoolSize那么就需要通过handler所指定的策略来处理此这个任务。 5 线程池中的线程数量大于 corePoolSize时如果某线程处理完任务后进入空闲状态空闲时间超过keepAliveTime该线程将被终止。这样线程池可以动态的调整池中的线程数到corePoolSize。 重点已经标红处理了在线程达到corePoolSize个数时超过的任务是先放在队列里面的 问题当任务很多又很耗时比如http请求IO密集型队列长度怎么设置过长容易造成任务堆积甚至OOM最大线程数的设置也将变的没有意义过短又容易将丢弃任务tomcat至少要保证请求尽可能交给业务系统去处理 tomcat线程池 在AbstractEndpoint中调用createExecutor方法自定义线程池 public void createExecutor() {internalExecutor true;TaskQueue taskqueue new TaskQueue();TaskThreadFactory tf new TaskThreadFactory(getName() -exec-, daemon, getThreadPriority());executor new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);taskqueue.setParent( (ThreadPoolExecutor) executor);}那么首先看ThreadPoolExecutor的excute方法 public void execute(Runnable command, long timeout, TimeUnit unit) {submittedCount.incrementAndGet();try {super.execute(command);} catch (RejectedExecutionException rx) {if (super.getQueue() instanceof TaskQueue) {final TaskQueue queue (TaskQueue)super.getQueue();try {if (!queue.force(command, timeout, unit)) {submittedCount.decrementAndGet();throw new RejectedExecutionException(sm.getString(threadPoolExecutor.queueFull));}} catch (InterruptedException x) {submittedCount.decrementAndGet();throw new RejectedExecutionException(x);}} else {submittedCount.decrementAndGet();throw rx;}}}tomcat中的线程池有一个额外的属性submittedCount你可以简单的理解为就是一个计数器每当有一个任务执行在执行时submittedCount就会加1当任务执行完成后submittedCount就会减1具体记录这个数字有什么作用继续往下看就知道了。 核心还在是父类的的excute方法 public void execute(Runnable command) {if (command null)throw new NullPointerException();/** Proceed in 3 steps:** 1. If fewer than corePoolSize threads are running, try to* start a new thread with the given command as its first* task. The call to addWorker atomically checks runState and* workerCount, and so prevents false alarms that would add* threads when it shouldnt, by returning false.** 2. If a task can be successfully queued, then we still need* to double-check whether we should have added a thread* (because existing ones died since last checking) or that* the pool shut down since entry into this method. So we* recheck state and if necessary roll back the enqueuing if* stopped, or start a new thread if there are none.** 3. If we cannot queue task, then we try to add a new* thread. If it fails, we know we are shut down or saturated* and so reject the task.*/int c ctl.get();if (workerCountOf(c) corePoolSize) {if (addWorker(command, true))return;c ctl.get();}if (isRunning(c) workQueue.offer(command)) {int recheck ctl.get();if (! isRunning(recheck) remove(command))reject(command);else if (workerCountOf(recheck) 0)addWorker(null, false);}else if (!addWorker(command, false))reject(command);}如果当前worker的数量小于核心线程池调用addWorker如果任务能成功入队并且需要增加一个线程线程池未关闭并且没有工作线程调用addWorker如果任务入队失败那么尝试添加一个新线程。如果失败了拒绝这项任务。 什么是ctl 我们看到线程池ThreadPoolExecutor内部是通过AtomicInteger类型的 ctl变量来控制运行状态和线程个数在通过AtomicInteger源码知道器内部就是维护了一个int类型的value值如下 private volatile int value;那么通过一个值如何维护状态和个数两个值呢那么接下来通过底层源码来看大神Doug Lea是如何设计的。 private static final int COUNT_BITS Integer.SIZE - 3;private static final int CAPACITY (1 COUNT_BITS) - 1;// 取高三位表示以下运行时的状态// runState is stored in the high-order bitsprivate static final int RUNNING -1 COUNT_BITS;private static final int SHUTDOWN 0 COUNT_BITS;private static final int STOP 1 COUNT_BITS;private static final int TIDYING 2 COUNT_BITS;private static final int TERMINATED 3 COUNT_BITS;/*** 各个值的二进制表示** 1111 1111 1111 1111 1111 1111 1111 1111 (-1) * 0000 0000 0000 0000 0000 0000 0000 0000 (0) * 0000 0000 0000 0000 0000 0000 0000 0001 (1) * 0000 0000 0000 0000 0000 0000 0000 0010 (2) * 0000 0000 0000 0000 0000 0000 0000 0011 (3)** 【分析】* 初始容量值高三位全是0低29位全是1后续操作会以此为基础进行操作* CAPACITY 000 1 1111 1111 1111 1111 1111 1111 1111** ---------------3位-1位 -28位---* 【前三位表明状态位后29位表明线程个数即 2^29 - 1 基本够用了】** RUNNING(-536870912) 111 0 0000 0000 0000 0000 0000 0000 0000* SHUTDOWN(0) 000 0 0000 0000 0000 0000 0000 0000 0000* STOP(536870912) 001 0 0000 0000 0000 0000 0000 0000 0000* TIDYING(1073741824) 010 0 0000 0000 0000 0000 0000 0000 0000* TERMINATED(1610612736) 011 0 0000 0000 0000 0000 0000 0000 0000* */ 结论就是前三位表明状态位后29位表明线程个数即 2^29 - 1 基本够用了 TaskQueue的offer()方法 既然tomcat用了自己的队列接下来看一下自定义的TaskQueue类 上述源码已经知道是否调用addWorker方法取决于TaskQueue的offer()方法要返回false结果暂不考虑入队成功但是worker随后被销毁的情况 LinkedBlockingQueue的实现 TaskQueue继承于LinkedBlockingQueue那么先看LinkedBlockingQueue的offer实现 public boolean offer(E e) {if (e null) throw new NullPointerException();final AtomicInteger count this.count;if (count.get() capacity)return false;final int c;final NodeE node new NodeE(e);final ReentrantLock putLock this.putLock;putLock.lock();try {if (count.get() capacity)return false;enqueue(node);c count.getAndIncrement();if (c 1 capacity)notFull.signal();} finally {putLock.unlock();}if (c 0)signalNotEmpty();return true;}很简单队列中元素个数达到容量上限则返回false 这也能解释为什么jdk线程池是队列满了才会继续新增线程至最大线程数 tomcat实现TaskQueue 首先TaskQueue是继承LinkedBlockingQueue的 public class TaskQueue extends LinkedBlockingQueueRunnable 再看offer方法 public boolean offer(Runnable o) {//we cant do any checksif (parentnull) return super.offer(o);//we are maxed out on threads, simply queue the objectif (parent.getPoolSize() parent.getMaximumPoolSize()) return super.offer(o);//we have idle threads, just add it to the queueif (parent.getSubmittedCount()(parent.getPoolSize())) return super.offer(o);//if we have less threads than maximum force creation of a new threadif (parent.getPoolSize()parent.getMaximumPoolSize()) return false;//if we reached here, we need to add it to the queuereturn super.offer(o);}注释解释的很明显了 如果当前活跃的线程数等于最大线程数那么就不能创建线程了因此直接放入队列中如果当前提交的任务数小于等于当前活跃的线程数表示还有空闲线程直接添加到队列让线程去执行即可。此处也终于看到了parent.getSubmittedCount方法用来获取当前提交的任务数每当有一个任务执行在执行时submittedCount就会加1当任务执行完成后submittedCount就会减1再校验下当前活跃线程数是否小于最大线程数如果小于此时就可以创建新的线程了。如果以上都不符合那就代表既没有空闲线程又达到了最大线程数也只能放队列了但是不需要新建线程 因此Tomcat的线程池策略是如果没有空闲线程且线程数大于核心线程配置时继续增加线程至最大核心数为止。 两者对比 tomcat的线程池实现相比jdk实现有以下几点不同 队列无限长高qps时基本不会丢弃任务但是会有OOM的风险但是一般单台服务器qps基本不会超过两千达到最大线程数之后才会放入队列低qps时可以快速请求响应不用排队但是若qps不稳定会频繁创建销毁线程对cpu不够友好 行文至此tomcat为什么要自定义线程池已经讲完了接下来会补充一下worker的源码分析 worker原理 简介 Worker是ThreadPoolExecutor中的内部类线程池中的线程都会被封装成一个Worker类对象ThreadPoolExecutor维护的其实就是一组Worker对象其中用集合workers存储这些Worker对象 Worker类中有两个属性一个是firstTask用来保存传入线程池中的任务一个是thread是在构造Worker对象的时候利用ThreadFactory来创建的线程用来处理线程池队列中的任务 Worker继承AQS使用AQS实现独占锁并且是不可重入的构造Worker对象的时候会把锁资源状态设置成-1因为新增的线程还没有处理过任务是不允许被中断的 代码如下 private final class Worker extends AbstractQueuedSynchronizer implements Runnable {/*** This class will never be serialized, but we provide a* serialVersionUID to suppress a javac warning.*/private static final long serialVersionUID 6138294804551838833L;/** 这个就是worker持有的线程也就是线程池中的线程 */ final Thread thread;/** 这个就是提交给线程池的任务 */ Runnable firstTask;/** 每一个线程执行的任务数量的计数器 */ volatile long completedTasks;/*** 我们在调用addWorker方法的时候就会调用这个构造方法有可能是创建新线程并执行任务那么firstTask就是传给线程池要执行的任务如果只是了* 单纯的想创建一个线程只需要传入null就可以*/Worker(Runnable firstTask) {setState(-1); // inhibit interrupts until runWorkerthis.firstTask firstTask;// 这个是通过线程工厂类创建一个线程也就是给线程池创建一个线程this.thread getThreadFactory().newThread(this); }/** Delegates main run loop to outer runWorker */public void run() {runWorker(this);}} worker其实就是一个Runable其也是需要构造成一个Thread对象然后调用Thread.start()方法运行的。只不过在worker的run方法中是定义了一个runWoker的方法。这个方法的主要内容从 for 循环不停的从task队列中获取对应的runable的task然后同步调用这个task的run()方法。其实就是在某个线程中不停的拿队列中的任务进行执行。 runWorker 上文已经知道线程池添加一个线程是通过调用addWorker方法在调用addWorker成功后则会执行Worker对象的run方法进入runWorker方法逻辑 final void runWorker(ThreadPoolExecutor.Worker w) {// 获取当前线程其实这个当前线程就是worker对象持有的线程从线程池中拿到的任务就是由这个线程执行的Thread wt Thread.currentThread();// 在构造Worker对象的时候会把一个任务添加进Worker对象// 因此需要把其作为新增线程的第一个任务来执行Runnable task w.firstTask;// 上面已经将该任务拿出来准备进行执行了将firstTask取出赋值给task则需要将该worker对象即线程池中的线程对象持有的任务清空w.firstTask null;// 将AQS锁资源的状态由-1变成0运行该线程进行中断 因为在创建的时候将state设为-1了现在开始执行任务了也就需要加锁了所以要把state再重新变为0这样在后面执行任务的时候才能用来加锁保证任务在执行过程中不会出现并发异常// 解锁w.unlock();// 用来判断执行任务的过程中是否出现了异常boolean completedAbruptly true;try {// 线程池中的线程循环处理线程池中的任务直到线程池中的所有任务都被处理完后则跳出循环while (task ! null || (task getTask()) ! null) { // 这一步的getTask()就说明Worker一直在轮询的从队列中获取任务getTask()方法将从队列获取到的任务返回赋值给task// 给该worker加锁一个线程只处理一个任务。注意加锁是给worker线程加锁不是给任务线程加锁因为worker线程之前一直在轮询地在队列中取任务但是当执行任务的时候为了避免执行任务出现异常就对其加锁w.lock();// 线程池是否是STOP状态// 如果是则确保当前线程是中断状态// 如果不是则确保当前线程不是中断状态if ((runStateAtLeast(ctl.get(), STOP) ||(Thread.interrupted() runStateAtLeast(ctl.get(), STOP))) !wt.isInterrupted())// 注意这里中断的是当前线程也就是worker对象持有的线程wt.interrupt();try {// 扩展使用在执行任务的run方法之前执行beforeExecute(wt, task);// 记录执行任务过程中出现的异常Throwable thrown null;try {// 执行任务的run方法 当前线程环境就是worker对象持有的线程所以本质就是woker对象在执行task任务的run()方法task.run();} catch (RuntimeException x) {thrown x; throw x;} catch (Error x) {thrown x; throw x;} catch (Throwable x) {thrown x; throw new Error(x);} finally {// 扩展使用在执行任务的run方法之后执行afterExecute(task, thrown);}} finally {// 执行完任务后就将任务对象清空task null;w.completedTasks; // 该worker已经完成的任务数1w.unlock(); // 将worker线程地锁释放}}// 正常执行完任务completedAbruptly false;} finally {// 线程池中所有的任务都处理完后或者执行任务的过程中出现了异常就会执行该方法processWorkerExit(w, completedAbruptly);} }这个方法主要做几件事 如果 task 不为空则开始执行 task如果 task 为空则通过 getTask()再去取任务并赋值给 task如果取到的 Runnable 不为空则执行该任务执行完毕后通过 while 循环继续 getTask()取任务如果 getTask()取到的任务依然是空那么整个 runWorker()方法执行完毕 这个方法比较简单如果忽略状态检测和锁的内容本质就是如果有第一个任务就先执行之之后再从任务队列中取任务来执行获取任务是通过getTask()来进行的。 到这里也就明白了线程池是怎么复用有限的线程数来执行大量的任务 那么worker是如何获取任务的呢? 核心方法 getTask() 这个方法用来向队列中轮询地尝试获取任务。该方法也是ThreadPoolExecutor中的方法。 这里重要的地方是第二个 if 判断目的是控制线程池的有效线程数量。 由上文中的分析可以知道在执行 execute 方法时如果当前线程池的线程数量超过了 corePoolSize 且小于maximumPoolSize并且 workQueue 已满时则可以增加工作线程但这时如果超时没有获取到任务也就是 timedOut 为 true 的情况说明 workQueue 已经为空了也就说明了当前线程池中不需要那么多线程来执行任务了可以把多于 corePoolSize 数量的线程销毁掉保持线程数量在 corePoolSize 即可。 // 返回任务Runnable private Runnable getTask() {// timedOut表示 记录上一次从队列中获取任务是否超时boolean timedOut false; // Did the last poll() time out?// 自旋for (;;) {// 这一部分是判断线程池状态// 获取线程池的状态和线程池中线程数量组成的整形字段32位// 高3位代表线程池的状态低29位代表线程池中线程的数量int c ctl.get();// 获取高3位的值即线程池的状态int rs runStateOf(c);// 如果线程池状态不是Running状态并且 线程也不是SHUTDOWN状态 或者任务队列已空if (rs SHUTDOWN (rs STOP || workQueue.isEmpty())) {// 则将线程池中的线程数量减1 就是说该线程已经不是运行状态了所以要这个worker线程也没有用了直接将该worker去掉。这个是原子操作decrementWorkerCount();//返回一个空任务因为// 1如果任务队列已空则想返回任务也没有// 2:如果线程池处于STOP或者之上的状态则线程池不允许再处理任务return null;}// 这一部分是判断线程池有效线程数量// 获取低29位的值即线程池中线程的数量int wc workerCountOf(c);// timed是否需要进行超时控制// allowCoreThreadTimeOut默认false// 当线程池中线程的数量没有达到核心线程数量时获取任务的时候允许超时 如果将allowCoreThreadTimeOut设为true那也不允许超时// 当线程池中线程的数量超过核心线程数量时获取任务的时候不允许超时 boolean timed allowCoreThreadTimeOut || wc corePoolSize; // 这个很好理解// wc maximumPoolSize的情况是因为可能在此方法执行阶段同时执行了setMaximumPoolSize方法// timed timedOut 如果为true表示当前操作需要进行超时控制并且上次从阻塞队列中获取任务发生了超时// 接下来判断如果有效线程数量大于1或者阻塞队列是空的那么尝试将workerCount减1// 如果减1失败则continue返回重试// 如果wc 1时也就说明当前线程是线程池中唯一的一个线程了。if ((wc maximumPoolSize || (timed timedOut)) (wc 1 || workQueue.isEmpty())) {if (compareAndDecrementWorkerCount(c))return null;continue;}// 如果上面都没问题就可以获取任务了try {// 获取任务// 如果timed true 说明需要做超时控制则根据keepAliveTime设置的时间内阻塞等待从队列中获取任务// 如果timed false说明不需要做超时控制则阻塞直到从队列中获取到任务为止Runnable r timed ?workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :workQueue.take();// 如果获取到任务则把任务返回if (r ! null)return r;// 执行到这里说明在允许的时间内没有获取到任务timedOut true;} catch (InterruptedException retry) {// 获取任务没有超时但是出现异常了将timedOut设置为falsetimedOut false;}} } 注意这里取任务会根据工作线程的数量判断是使用BlockingQueue的poll(timeout, unit)方法还是take()方法。 poll(timeout, unit)方法会在超时时返回null如果timeout0队列为空时直接返回null。 take()方法会一直阻塞直到取到任务或抛出中断异常。 所以如果keepAliveTime设置为0当任务队列为空时非核心线程取不出来任务会立即结束其生命周期。 当允许超时控制时workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) 会在keepAliveTime后返回null返回null的结果是退出完成循环销毁当前线程这就说明了keepAliveTime参数的含义线程最大空闲时间了 提出一个问题这个keepAliveTime参数是否对核心线程也生效呢文末会有答案 那么接下来worker是如何销毁的呢 核心方法 processWorkerExit() runWorker 的 while 循环执行完毕以后在 finally 中会调用 processWorkerExit()方法来销毁工作线程。该方法就是判断当前线程是需要将其删除还是继续执行任务。该方法也是ThreadPoolExecutor中的方法。 private void processWorkerExit(ThreadPoolExecutor.Worker w, boolean completedAbruptly) {// 如果 completedAbruptly true 则线程执行任务的时候出现了异常需要从线程池中减少一个线程// 如果 completedAbruptly false则执行getTask方法的时候已经减1这里无需在进行减1操作if (completedAbruptly)decrementWorkerCount();// 获取线程池的锁因为后面是线程池的操作为了并发安全需要对线程池加锁final ReentrantLock mainLock this.mainLock;// 线程池加锁mainLock.lock();try {// 统计该线程池完成的任务数completedTaskCount w.completedTasks;// 从线程池中移除一个工作线程 works是线程池持有的一个集合 workers.remove(w); // 将没用的worker去掉也就是当前传入的worker} finally {// 线程池解锁mainLock.unlock();}// 根据线程池的状态决定是否结束该线程池tryTerminate(); // 钩子方法// 判断线程池是否需要增加线程// 获取线程池的状态int c ctl.get();// -当线程池是RUNNING或SHUTDOWN状态时// --如果worker是异常结束即completedAbruptly为false那么会直接addWorker// ---如果allowCoreThreadTimeOut true并且等待队列有任务至少保留一个worker// ---如果allowCoreThreadTimeOut false活跃线程数不少于corePoolSizeif (runStateLessThan(c, STOP)) { // 线程池状态小于STOP就说明当前线程池是RUNNING或SHUTDOWN状态// 如果worker是异常结束的不进入下面的分支直接去addWorkerif (!completedAbruptly) {// 根据allowCoreThreadTimeOut的值来设置线程池中最少的活跃线程数是0还是corePoolSizeint min allowCoreThreadTimeOut ? 0 : corePoolSize;// 如果等待队列中有任务要至少保留一个workerif (min 0 ! workQueue.isEmpty())// 至少保留一个workermin 1;// 如果活跃线程数大于等于min直接返回不需要再调用addWorker来增加线程池中的线程了if (workerCountOf(c) min)return; // replacement not needed}// 增加线程池中的workeraddWorker(null, false);} } 1.执行decrementWorkerCount方法将线程池中的线程数量减1 因为当前worker已经取出去任务了 如果 completedAbruptly true 则代表线程执行任务的时候出现了异常需要执行如果 completedAbruptly false则执行getTask方法的时候调用过decrementWorkerCount方法将线程池中的线程数量减1这里无需在进行减1操作 2.将worker从wokers集合中移除 3.根据线程池的状态决定是否结束该线程池 4.判断是否再调用addWorker方法 其中 int min allowCoreThreadTimeOut ? 0 : corePoolSize;根据allowCoreThreadTimeOut的值来设置线程池中最少的活跃线程数是0还是corePoolSize 如果worker是异常结束即completedAbruptly为false那么会直接addWorker如果allowCoreThreadTimeOut true并且等待队列有任务至少保留一个worker如果allowCoreThreadTimeOut false活跃线程数不少于corePoolSize 说明 如果核心线程出了异常也是会被销毁的只不过销毁后还会调用addWorker方法增加一个线程allowCoreThreadTimeOut为true时min为0则表明核心线程在allowCoreThreadTimeOut为true时也是会随着worker的销毁没有任务可取既空闲了keepAliveTime时间而销毁并且不会调用addWorker来增加一个线程 参考 https://blog.csdn.net/cy973071263/article/details/131484384 https://blog.csdn.net/u014307520/article/details/117787133 https://blog.csdn.net/kkkkk0826/article/details/103405813

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/914843.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

做爰全程的网站文安做网站的

使用 Tailwind CSS 完成导航栏效果 本文将向您介绍如何使用 Tailwind CSS 创建一个漂亮的导航栏。通过逐步演示和示例代码,您将学习如何使用 Tailwind CSS 的类来设计和定制导航栏的样式。 准备工作 在开始之前,请确保已经安装了 Tailwind CSS。如果没…

为你的数据选择合适的分布:8个实用的概率分布应用场景和选择指南

拿到数据想建模,但不知道用哪个分布?大部分教科书都在讲一堆你永远用不到的东西。实际工作中,你只需要掌握几个核心分布,然后知道什么时候该用哪个就够了。 这里是我在做分析、实验设计、风险建模时真正会用的8个分…

wordpress网站映射简历电子版模板免费下载

原标题:Linux Kernel 4.4.19 LTS长期支持版发布摘要:近日,内核开发者Greg Kroah-Hartman公布了长期支持的Linux 4.4 Kernel系列第19个维护版本的细节。Linux 4.4是目前最新的LTS内核分支,被Arch Linux, Solus和Ubuntu Linux等众多…

五百亿建站模板重庆建工集团股份有限公司官网

BigDeciaml1. BigDecimal1. BigDecimal 我们知道,关于金钱相关的计算,都用BigDeciaml数据类型, 来表示金额。所有关于金额的项目中不能缺少它的使用。 而我今天说说用这个类型,踩到的坑。 金额比较问题 带精度不适用equals比较。使用compar…

浙江网站建设推广公司哪家好百度服务电话

** Java学习 第三章 数组(三)排序算法 ** 主要内容:排序算法、排序算法横向比较、Arrays工具类的使用、数组常见异常 1.数组中涉及到的常见算法:排序算法 1.1 排序算法分类:内部排序和外部排序 1.2 十大内部排序算…

专业手机网站建设推荐长春几个火车站啊

科技巨头的AI之战持续上演,而财报季是一窥AI成色的重要窗口。 谷歌和微软这对在多个领域均正面对决的科技巨头,又在同一日发布了财报,而这次相比上季度,战局似乎迎来了反转。 上季度,谷歌不仅成功抵御了Bing联手ChatG…

龙岩做网站开发价格京津冀协同发展意义

mvn archetype:create -DgroupIdcom.mycompany.app -DartifactIdmyWeb -DarchetypeArtifactIdmaven-archetype-webapp 转载于:https://www.cnblogs.com/alaricblog/p/3278239.html

网站特效 站长做属于公司的网站有什么好处

计算机网络21-40 以下是本文参考的资料 欢迎大家查收原版 本版本仅作个人笔记使用21、HTTPS是如何保证数据传输的安全,整体的流程是什么?(SSL是怎么工作保证安全)对称加密非对称加密消息认证码 (MAC)数字证书 22、如何保证公钥不被…

网站的关键词可以取消吗济南百度提升优化

作为一个芯片公司打杂人口,往往需要一个皮实耐打上天入地的编辑器… 一、先附上github路径,方便取走 git clone gitgithub.com:qqqw4549/vim_config_c_verilog.git 二、效果展示 支持ctrl]函数/模块跳转,支持cscope字串全局代码搜索 依赖&am…

天津百度爱采购重庆整站优化的电话销售

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 Web服务器收到一个http请求,会针对每个请求创建一个HttpServletRequest和HttpServletResponse对象, 从客户端取…

如何宣传商务网站网站怎样优化seo

目录 流程控制之条件判断 2.1.if语句语法 2.1.1单分支结构 2.1.2双分支结构 2.1.3多分支结构 2.2.案例 例一: 例2: 例3: 例4: 例5: 例6: 例7: 例8: 例9: 2.3.case多条件判断 2.3.1.格式 2.3.2.执行过程 例10: 流程控制之条件判断 2.1.if语句语法 2.1.1单分…

佛山市手机网站建设企业企业大黄页

/Bin存放系统命令 /etc存放系统命令及配置文件的数据库 /lib存放C语言的库函数、数据库 /mnt存放可拆装的软件 /Tmp存放临时文件 /user存放用户目录 转载于:https://www.cnblogs.com/Ewin/archive/2008/12/22/1360111.html

怎么查找网站是谁做的建站开发软件

每个开发都会涉及到一个工作,就是网站开发。开发过程势必会涉及到需要对网站加速的部分,很多开发同学对此都很是头疼。 想让网站跑起来飞快,必须用上个网站加速神器,很多人都会推荐CDN。CDN的原理就是把网站文件提前搬到全国各地…

网站建设维护课件ppt销售渠道策略

使用PostMan可以方便快速的进行跨域测试。 只需要在请求头中手动添加一个Origin的标头,声明需要跨域跨到的域(IP:端口)就行,其余参数PostMan会自动生成。添加此标头后,请求会被做为一条跨域的请求来进行处…

资中移动网站建设wordpress move导入数据

个人主页:insist--个人主页​​​​​​ 本文专栏:网络基础——带你走进网络世界 本专栏会持续更新网络基础知识,希望大家多多支持,让我们一起探索这个神奇而广阔的网络世界。 目录 一、网络设备的概述 二、常见的网络设备 1、…

中国建设银行网站对公业务大连市建设学校网站

华为PPPOE配置实验 网络拓扑图拓扑说明电信ISP设备配置用户拨号路由器配置查看是否拨上号是否看不懂? 看不懂就对了,只是记录一下命令。至于所有原理,等想写了再写 网络拓扑图 拓扑说明 用户路由器用于模拟家用拨号路由器,该设备…

网站设计及建设合同怎么做网站地图的样式

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。 本文描述了如何使用…

西安网站建设哪家好一些移动免费网站建设

目录 1.Feign传文件报错,Feign不支持上传文件需要借助外面的依赖才可以实现上传 2.服务之间通过Feign相互调用传递DTO(实体对象)报错 1.Feign传文件报错,Feign不支持上传文件需要借助外面的依赖才可以实现上传 具体报错内容: FileUploadException: the request was reje…

河北高端网站设计公司集团公司网站推广方案怎么做

喜欢就关注我们吧!最新的 Windows Insiders Preview Build 为 WSL2 的命令行程序增加了新功能:wsl --mount,这个新参数支持在 WSL2 添加和挂载物理磁盘,用户通过它能访问 Windows 没有原生支持的 Linux 文件系统(例如 …

开设购物网站的方案wordpress微信营销

MySQL的表逻辑分区是一种数据库设计技术,它允许将一个表的数据分布在多个物理分区中,但在逻辑上仍然表现为一个单一的表。这种方式可以提高查询性能、简化数据管理,并有助于高效地进行大数据量的存储和访问。逻辑分区基于特定的规则&#xff…