看了不少文章以为都不能把keepAliveTime的意思说的很明白,但愿经过本身的理解把keepAliveTime说的明确一些java
先引用一句我以为相对说的比较明白的含义:当线程空闲时间达到keepAliveTime,该线程会退出,有两个疑问:一、线程为何会空闲 二、线程为何要退出spa
若是咱们不能把线程池各个参数的前因后果都梳理清楚实际上是很难明白keepAliveTime的含义的线程
咱们来举例说明:code
核心线程数10,最大线程数30,keepAliveTime是3秒blog
随着任务数量不断上升,线程池会不断的建立线程,直到到达核心线程数10,就不建立线程了,队列
这时多余的任务经过加入阻塞队列来运行,资源
当超出阻塞队列长度+核心线程数时,get
这时不得不扩大线程个数来知足当前任务的运行,这时就须要建立新的线程了(最大线程数起做用),上限是最大线程数30源码
那么超出核心线程数10并小于最大线程数30的可能新建立的这20个线程至关因而“借”的,若是这20个线程空闲时间超过keepAliveTime,就会被退出it
咱们来看开头提到的两个问题:
一、线程为何会空闲
二、线程为何要退出
答:
一、没有任务时线程就会空闲下来,在线程池中任务是任务(Runnale)线程是线程(Worker)
二、一般超出核心线程的线程是“借”的,也就是说超出核心线程的状况算是一种可以预见的异常状况,而且这种状况并不经常发生(若是经常发生,那我想你应该调整你的核心线程数了),因此这种不常常发生而建立的线程为了不资源浪费就应该要退出
咱们须要看一下java.util.concurrent.ThreadPoolExecutor#getTask源码来验证上面一段话的含义:
int wc = workerCountOf(c); // Are workers subject to culling? 是否屠宰workers //当allowCoreThreadTimeOut为true或者当前任务数超过核心线程数时,timed为true boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; …… try { Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) ://若是timed为true说明worker有可能要被关闭,这里调用的代码含义:若是超过keepAliveTime纳秒还没取到任务,就返回null,后面会调用processWorkerExit把worker关闭 workQueue.take();//不然任务队列为空就阻塞在这里,直到任务队列再有任务 if (r != null) return r;
10个核心线程会不会退出,由下面的参数决定:
allowCoreThreadTimeout:是否容许核心线程空闲退出,默认值为false
经过实验证实和上文代码workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)证实,是直接不等待退出,而不是永远不退出
这样咱们就须要注意了,这个值设置为0 并非个很好的作法(除非场景中任务数量极少能超出核心线程数),若是任务数频繁超出核心线程数,这个值须要评估设定为合理值尽可能避免线程开启关闭的动做
(上图,若是永远不退出,那么workers就不是10 而是45)