Java线程池关闭遵循单向不可逆状态迁移机制:shutdown()触发RUNNING→SHUTDOWN→TIDYING→TERMINATED,拒绝新任务但处理队列及运行中任务;shutdownNow()直接进入STOP状态,清空队列并中断线程;awaitTermination()仅等待终止不改变状态;ctl变量高3位存状态,低29位存线程数。

Java 线程池的关闭不是“一刀切”的操作,而是遵循一套严格、单向、不可逆的状态迁移机制。理解 shutdown 和 stop 的演变过程,关键在于看清每个状态的触发条件、行为边界,以及它们如何推动线程池走向终结。
shutdown() 触发平滑关闭路径:RUNNING → SHUTDOWN → TIDYING → TERMINATED
调用 shutdown() 后,线程池立即进入 SHUTDOWN 状态:
- 不再接受新提交的任务(
submit()或execute()会抛出RejectedExecutionException) - 但继续处理工作队列中已排队的任务,也允许正在运行的线程完成当前任务
- 同时中断所有空闲的 Worker 线程(避免它们长期阻塞在队列取任务上)
当满足两个条件时——所有任务(包括队列中剩余的 + 正在运行的)均已结束,且工作线程数降为 0——线程池自动转入 TIDYING 状态,并同步调用 terminated() 钩子方法;该方法执行完毕后,状态变为 TERMINATED,线程池彻底终止。
shutdownNow() 触发强制关闭路径:RUNNING/SHUTDOWN → STOP → TIDYING → TERMINATED
调用 shutdownNow() 会跳过 SHUTDOWN,直接将状态设为 STOP:
立即学习“Java免费学习笔记(深入)”;
- 拒绝所有新任务
- 清空工作队列,返回其中未执行的
Runnable列表 - 尝试对所有 Worker 线程调用
interrupt()(注意:是否真正中断取决于线程内部是否响应中断,如是否在sleep、wait或阻塞 I/O 中)
此后,只要所有任务停止、线程数归零,线程池同样会自动推进至 TIDYING → TERMINATED。也就是说,STOP 和 SHUTDOWN 最终都汇入同一终结流程,只是中间行为差异显著。
awaitTermination() 是等待器,不是状态切换器
awaitTermination() 不改变线程池状态,它只是阻塞调用线程,轮询判断是否已达 TERMINATED:
- 常与
shutdown()配合使用,实现“发起关闭 + 等待完成”的语义 - 可设置超时时间,超时后即使未完全终止也会返回
false,避免无限等待 - 内部依赖
termination.signalAll()(由tryTerminate()在进入 TIDYING 时触发),唤醒所有等待者
状态本质:一个 int 的高低位分工
线程池状态实际存储在 ctl 这个 AtomicInteger 中:
- 高 3 位表示运行状态(RUNNING=111, SHUTDOWN=000, STOP=001, TIDYING=010, TERMINATED=011)
- 低 29 位表示当前工作线程数量
- 状态迁移靠 CAS 操作保证原子性,因此整个生命周期是线程安全且不可逆的


















