只要小于核心线程,新进来的都会创建线程。即使有空闲的线程存在,也会创建新 ,空闲线程只会监听队列。所以核心线程不宜过大,过大并且有保持时间,cup会高,并发持续积压后最终响应慢
当 allowCoreThreadTimeOut = true,所有的线程在空闲时,都会等待5秒销毁,包括核心线程,总线程=0
线程并非在创建时就标记了核心和非核心,只是在销毁的时候判断是否核心已满进行销毁与否,并不会指定某一个线程为核心线程
线程池状态在什么情况下改变?
1 线程池被一旦被创建,就处于RUNNING状态
2 调用shutdown()方法时,线程池由RUNNING -> SHUTDOWN。
3 调用线程池的shutdownNow()方法时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
4 所有的任务都销毁了,workCount 为 0,线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated()。因为terminated()在ThreadPoolExecutor类中是空的,所以用户想在线程池变为TIDYING时进行相应的处理;可以通过重载terminated()函数来实现。
当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。
当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
5.TERMINATED:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。
场景
核心线程数2
最大线程3
有界队列长度5
keepAliveTime 5秒
默认的异常策略
allowCoreThreadTimeOut使用默认值 保持核心线程不销毁
案例:
初始化 总线程数=0,(调用prestartAllCoreThreads()方法可以初始化核心线程数 总线程数=2)
1 第一个线程进入,小于核心线程,创建新线程,任务执行结束后,进入阻塞,总线程数=1
2 第二个线程进入,小于核心线程,创建新线程,任务执行结束后,进入阻塞,总线程数=2
3 第三个线程进入,大于等于核心线程,放入队列,一个核心线程取出,去执行任务,任务结束,线程进入阻塞,总线程数=2
4 一次进入5个线程,大于等于核心线程,全部放入队列,核心线程去执行,任务结束,线程进入阻塞,总线程数=2
5 一次进入6个线程,大于等于核心线程,放入队列5个,队列满,小于最大线程数,新建一个线程执行这个任务,总线程数=3,全部执行结束后,其中一个线程在keepAliveTime 5秒后销毁(while返回null,JVM自动回收)总线程数=2
6 一次进入7个线程,放入队列5个,新建一个,总线程数=3,队列满,大于等于最大线程3. 最后一个线程走默认异常策略,抛异常,全部执行结束后,其中一个线程5秒后销毁