shutdown()和shutdownNow()的核心差异在于关闭方式:前者进入SHUTDOWN状态,等待已提交任务(含运行中和队列中)自然完成,不中断线程;后者进入STOP状态,尝试中断所有工作线程并清空队列,返回未执行任务列表,但中断效果依赖任务是否响应中断。

shutdown() 和 shutdownNow() 的核心差异,不在于“要不要关”,而在于“怎么关”——前者让任务自然跑完再收工,后者直接拍停执行中的线程并清空队列。
shutdown():等待所有已提交任务完成
调用后线程池立即进入 SHUTDOWN 状态,不再接受新任务,但会继续处理两部分任务:
- 正在运行的任务:不受干扰,正常执行至结束
- 任务队列中已入队但未开始执行的任务:逐个取出、执行完毕
它不会中断任何线程,也不返回任何任务信息。适合对数据一致性要求高的场景,比如订单结算、日志落盘、数据库批量写入等,必须确保每个提交的任务都落地。
shutdownNow():尝试中断执行中任务 + 清空待执行队列
调用后线程池立刻转为 STOP 状态,行为更激进:
- 对所有工作线程(无论是否空闲)调用 Thread.interrupt()
- 从任务队列中移出所有尚未执行的 Runnable,并以 List
形式返回,供调用方决定如何处置(如重试、记录、丢弃) - 正在执行的任务是否真正停止,取决于任务本身是否响应中断
例如:任务里有 Thread.sleep(5000),被 interrupt 后会抛出 InterruptedException 并退出;但若只是纯计算循环且未检查 Thread.currentThread().isInterrupted(),该任务仍会继续跑完。
实际关闭流程中常被忽略的关键点
仅调用 shutdown() 或 shutdownNow() 并不等于线程池已终止。还需配合 awaitTermination() 主动等待:
- shutdown() 后建议调用
awaitTermination(timeout, unit),设定合理超时时间,避免主线程无限等待 - 若超时后仍未终止,可考虑补调 shutdownNow() 强制兜底
- 任务内部需主动响应中断:在循环中定期检查中断状态,在 catch InterruptedException 后做资源清理和状态回滚
否则可能出现线程池看似关闭,实则仍有线程卡在阻塞或死循环中,导致 JVM 无法正常退出。

















