线程池运行基本逻辑
执行顺序是C->Q->M
可以把线程池理解成一个黑心工厂,工厂老板只顾了5个核心常驻员工,当工作任务不多时让这5个员工来处理,处理不过来的任务就先堆放到仓库里面等后面有人力了慢慢处理,如果仓库也堆满了,就雇一些临时员工来帮忙处理,等任务处理完了,仓库也没有积压了就干掉临时员工,核心worker加上临时worker一共不会超过max
线程池逻辑细节
一、非code线程超过keepAlive时间后销毁的原理
1、当线程数大于core时,timed为true,进行期限等待,从阻塞队列获取任务使用keepAlive作为获取超时时间workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)。当线程数小于core时使用take无限期等待Queue中获取任务
2、当获取不到结果时线程执行内部变量的timeout被置为true,当worker的数量大于核心线程数时time是true,java.util.concurrent.ThreadPoolExecutor#getTask()会return null。compareAndDecrementWorkerCount这个CAS操作确保了当并发发生时只有一个线程return null
3、java.util.concurrent.ThreadPoolExecutor#runWorker(java.util.concurrent.ThreadPoolExecutor.Worker)中while条件不满足,runWorker执行结束,线程随之结束销毁,并从workers中删除自身worker
二、线程池是如何保证code线程不被销毁的呢?
allowCoreThreadTimeOut默认false
1、当allowCoreThreadTimeOut为true时即使线程数小于core也是会销毁线程
2、当allowCoreThreadTimeOut为false时,在ThreadPoolExecutor#getTask()中会判断线程数量大于code时才会return null去销毁线程
核心线程和非核心线程做的事情并没有区别,线程池只确保整体线程数量符合预期