深圳企业建站公司,网站系统性能定义,免费注册微信小程序,照片展示网站模板免费下载1、类比介绍 假如有一个工厂#xff0c;工厂里面有10个工人#xff0c;每个工人同时只能做一件任务。 因此只要当10个工人中有工人是空闲的#xff0c;来了任务就分配给空闲的工人做#xff1b; 当10个工人都有任务在做时#xff0c;如果还来了任务#xff0c;就把任务进…1、类比介绍 假如有一个工厂工厂里面有10个工人每个工人同时只能做一件任务。 因此只要当10个工人中有工人是空闲的来了任务就分配给空闲的工人做 当10个工人都有任务在做时如果还来了任务就把任务进行排队等待 如果说新任务数目增长的速度远远大于工人做任务的速度那么此时工厂主管可能会想补救措施比如重新招4个临时工人进来 然后就将任务也分配给这4个临时工人做 如果说着14个工人做任务的速度还是不够此时工厂主管可能就要考虑不再接收新的任务或者抛弃前面的一些任务了。 当这14个工人当中有人空闲时而新任务增长的速度又比较缓慢工厂主管可能就考虑辞掉4个临时工了只保持原来的10个工人毕竟请额外的工人是要花钱的。 这个例子中的corePoolSize就是10而maximumPoolSize就是14104。 也就是说corePoolSize就是线程池大小maximumPoolSize在我看来是线程池的一种补救措施即任务量突然过大时的一种补救措施。 2、源码分析 在ThreadPoolExecutor类中最核心的任务提交方法是execute()方法虽然通过submit也可以提交任务但是实际上submit方法里面最终调用的还是execute()方法所以我们只需要研究execute()方法的实现原理即可 public void execute(Runnable command) {if (command null)throw new NullPointerException();if (poolSize corePoolSize || !addIfUnderCorePoolSize(command)) {if (runState RUNNING workQueue.offer(command)) {if (runState ! RUNNING || poolSize 0)ensureQueuedTaskHandled(command);}else if (!addIfUnderMaximumPoolSize(command))reject(command); // is shutdown or saturated}
} 在addThread方法中首先用提交的任务创建了一个Worker对象然后调用线程工厂threadFactory创建了一个新的线程t然后将线程t的引用赋值给了Worker对象的成员变量thread接着通过workers.add(w)将Worker对象添加到工作集当中。 private Thread addThread(Runnable firstTask) {Worker w new Worker(firstTask);Thread t threadFactory.newThread(w); //创建一个线程执行任务 if (t ! null) {w.thread t; //将创建的线程的引用赋值为w的成员变量 workers.add(w);int nt poolSize; //当前线程数加1 if (nt largestPoolSize)largestPoolSize nt;}return t;
} 下面总结一下 1首先要清楚corePoolSize和maximumPoolSize的含义 2其次要知道Worker是用来起到什么作用的 3要知道任务提交给线程池之后的处理策略这里总结一下主要有4点 如果当前线程池中的线程数目小于corePoolSize则每来一个任务就会创建一个线程去执行这个任务如果当前线程池中的线程数目corePoolSize则每来一个任务会尝试将其添加到任务缓存队列当中若添加成功则该任务会等待空闲线程将其取出去执行若添加失败一般来说是任务缓存队列已满则会尝试创建新的线程去执行这个任务如果当前线程池中的线程数目达到maximumPoolSize则会采取任务拒绝策略进行处理如果线程池中的线程数量大于 corePoolSize时如果某线程空闲时间超过keepAliveTime线程将被终止直至线程池中的线程数目不大于corePoolSize如果允许为核心池中的线程设置存活时间那么核心池中的线程空闲时间超过keepAliveTime线程也会被终止。3.线程池中的线程初始化 默认情况下创建线程池之后线程池中是没有线程的需要提交任务之后才会创建线程。 在实际中如果需要线程池创建之后立即创建线程可以通过以下两个方法办到 prestartCoreThread()初始化一个核心线程prestartAllCoreThreads()初始化所有核心线程 4.任务缓存队列及排队策略 在前面我们多次提到了任务缓存队列即workQueue它用来存放等待执行的任务。 workQueue的类型为BlockingQueueRunnable通常可以取下面三种类型 1ArrayBlockingQueue基于数组的先进先出队列此队列创建时必须指定大小 2LinkedBlockingQueue基于链表的先进先出队列如果创建时没有指定此队列大小则默认为Integer.MAX_VALUE 3synchronousQueue这个队列比较特殊它不会保存提交的任务而是将直接新建一个线程来执行新来的任务。 5.任务拒绝策略 当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize如果还有任务到来就会采取任务拒绝策略通常有以下四种策略 ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy也是丢弃任务但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy丢弃队列最前面的任务然后重新尝试执行任务重复此过程
ThreadPoolExecutor.CallerRunsPolicy由调用线程处理该任务 6.线程池的关闭 ThreadPoolExecutor提供了两个方法用于线程池的关闭分别是shutdown()和shutdownNow()其中 shutdown()不会立即终止线程池而是要等所有任务缓存队列中的任务都执行完后才终止但再也不会接受新的任务shutdownNow()立即终止线程池并尝试打断正在执行的任务并且清空任务缓存队列返回尚未执行的任务7.线程池容量的动态调整 ThreadPoolExecutor提供了动态调整线程池容量大小的方法setCorePoolSize()和setMaximumPoolSize() setCorePoolSize设置核心池大小setMaximumPoolSize设置线程池最大能创建的线程数目大小 当上述参数从小变大时ThreadPoolExecutor进行线程赋值还可能立即创建新的线程来执行任务。 转载于:https://www.cnblogs.com/chappell/p/9084496.html