主池控制状态ctl是一个原子整数,打包了两个概念字段workerCount,表示有效线程数runState,表示是否正在运行,正在关闭等为了打包成一个int,我们限制workerCount为(2^29 )-1(约 5 亿)个线程而不是 (2^31)-1(20 亿)个其他可表示的线程。 如果这在未来成为一个问题,可以将变量更改为 AtomicLong,并调整下面的移位/掩码常量。 但是在需要之前,这段代码使用 int 会更快更简单。 workerCount 是允许启动和不允许停止的工人数量。 该值可能与实际的活动线程数暂时不同,例如当 ThreadFactory 在被询问时未能创建线程时,以及退出线程在终止前仍在执行簿记时。 用户可见的池大小报告为工作人员集的当前大小。 runState 提供主要的生命周期控制,取值: RUNNING:接受新任务并处理排队任务 SHUTDOWN:不接受新任务,但处理排队任务 STOP:不接受新任务,不处理排队任务,并中断正在进行的任务 TIDYING:所有任务都已终止,workerCount 为零,转换到状态 TIDYING 的线程将运行 terminate() 钩子方法 TERMINATED: terminate() 已完成这些值之间的数字顺序很重要,以允许有序比较. runState 随时间单调增加,但不需要命中每个状态。 转换是: RUNNING -> SHUTDOWN 在调用 shutdown() 时,可能隐含在 finalize() 中(RUNNING 或 SHUTDOWN)-> STOP 在调用 shutdownNow() 时 SHUTDOWN -> TIDYING 当队列和池都为空时 STOP -> TIDYING当池为空时 TIDYING -> TERMINATED 当 terminate() 钩子方法完成时,在 awaitTermination() 中等待的线程将在状态达到 TERMINATED 时返回。 检测从 SHUTDOWN 到 TIDYING 的转换并不像您想要的那么直接,因为在非空之后队列可能会变空,在 SHUTDOWN 状态期间反之亦然,但是我们只能在看到它为空后看到 workerCount 时才终止是 0(有时需要重新检查——见下文)。
1、线程池启动的时候就会启动核心线程数吗?
不会,只有第一个任务加进来的时候会启动线程,你可以调用prestartAllCoreThreads和prestartCoreThread分别启动所有核心线程和启动单个核心线程。
2、线程池可以动态更改核心线程数吗?如果可以是什么流程呢?
可以更改,调用setCorePoolSize 即可。首先会判断当前工作的线程是否大于你设置的值,如果大于则会销毁闲置的线程。第二如果大于你之前设置的线程数,那么会从任务队列中获取线程并且比较二者最小值进行新建线程。
更改流程
更改的流程图
3、线程池当没有任务时,核心线程会销毁吗?
核心线程数默认是不会被回收的,如果需要回收核心线程数,需要调用下面的方法:
注意允许核心线程超时的条件是时间必须大于0。
4、线程池监控哪些指标呢?如何知道一个线程池的参数是不是合适的?
可以监控当前任务队列的任务大小,拒绝次数
线程池活跃度 = activeCount/maximumPoolSize。这个公式代表当活跃线程数趋向于maximumPoolSize的时候,代表线程负载趋高。事中,也可以从两方面来看线程池的过载判定条件,一个是发生了Reject异常,一个是队列中有等待任务(支持定制阈值)