Java线程池生命周期由ctl统一管理,状态按RUNNING→SHUTDOWN→STOP→TIDYING→TERMINATED严格单向迁移,通过CAS原子操作校验合法性,非法转换被静默忽略;安全等待终结需配合shutdown()与awaitTermination(),并可重写beforeExecute、afterExecute和terminated钩子方法感知阶段。

Java 线程池的生命周期由 ctl(一个 AtomicInteger)统一管理,其高 3 位表示运行状态,低 29 位表示工作线程数。状态切换不是随意的,而是严格遵循预定义的**有向状态机**:RUNNING → SHUTDOWN → STOP → TIDYING → TERMINATED。
五种状态的含义与触发条件
RUNNING:接受新任务,也处理队列中的任务。这是线程池创建后的初始状态。
SHUTDOWN:不接受新任务,但继续处理已提交到队列中的任务。调用 shutdown() 进入此状态。
STOP:不接受新任务,也不处理队列中的任务,并尝试中断所有正在执行的线程。调用 shutdownNow() 进入此状态。
TIDYING:所有任务已终止,工作线程数为 0,线程池即将进入终结状态。此时会调用 terminated() 钩子方法。
TERMINATED:线程池彻底终止,terminated() 执行完毕后自动转入该状态。
状态转换不可逆,且受保护检查
线程池内部所有状态变更都通过 compareAndSet 原子操作完成,并伴随状态合法性校验。例如:
- 只有 RUNNING 可以转为 SHUTDOWN(
shutdown())或 STOP(shutdownNow()) - SHUTDOWN 只能转为 STOP(再次调用
shutdownNow())或 TIDYING(当队列空、线程数为 0) - STOP 只能转为 TIDYING(当所有线程被标记为中断且实际停止)
- TIDYING 必然转为 TERMINATED(
terminated()返回后)
任何非法转换(如从 TERMINATED 再调 shutdown())会被静默忽略,不会抛异常,但返回 false。
如何安全地等待线程池终结
不能仅靠轮询 isTerminated(),而应结合 awaitTermination(long, TimeUnit):
立即学习“Java免费学习笔记(深入)”;
- 先调用
shutdown()或shutdownNow()触发状态迁移 - 再循环调用
awaitTermination(),它会在 TERMINATED 状态时返回 true,超时时返回 false - 若返回 false,可选择重试、强制 shutdownNow,或记录日志并放弃
注意:awaitTermination() 不会阻塞到所有线程真正死亡,只等待状态变为 TERMINATED —— 这依赖于线程池内部在满足条件后主动推进状态。
自定义行为:重写钩子方法
可通过继承 ThreadPoolExecutor 并重写以下受保护方法,在状态变化关键点插入逻辑:
-
beforeExecute(Thread t, Runnable r):任务执行前(RUNNING 中) -
afterExecute(Runnable r, Throwable t):任务执行后(无论成功/异常) -
terminated():状态变为 TIDYING 后、转为 TERMINATED 前执行(常用于资源清理)
这些方法本身不改变状态,但能帮你感知生命周期阶段,比如在 terminated() 中关闭数据库连接、释放文件句柄等。


















