必须先调用 shutdown() 再调用 awaittermination() 才能等待所有任务完成;若超时则调用 shutdownnow() 并再次 awaittermination(),且需设置合理超时时间(如30秒)并处理返回值。

要等待线程池中所有任务执行完毕,不能只靠 shutdown(),必须配合 awaitTermination() 使用;它会阻塞当前线程,直到所有已提交任务完成、线程池终止,或超时发生。
正确调用顺序:shutdown() + awaitTermination()
必须先调用 shutdown()(拒绝新任务,但允许已提交任务继续执行),再调用 awaitTermination()。如果跳过 shutdown(),awaitTermination() 会立即返回 false(因为线程池仍处于运行状态)。
executor.shutdown();boolean finished = executor.awaitTermination(10, TimeUnit.SECONDS);
处理超时情况:判断返回值并决定是否强制关闭
awaitTermination() 返回 true 表示所有任务已正常结束;返回 false 表示超时,此时线程池可能仍有活跃任务在运行。常见做法是:超时时调用 shutdownNow() 尝试中断正在执行的任务。
- 若
awaitTermination()返回false,可调用executor.shutdownNow(); - 之后可再次调用
awaitTermination()等待被中断任务彻底结束(如清理逻辑) - 注意:
shutdownNow()不保证任务立即停止,仅发送中断信号,任务需自行响应Thread.interrupted()或检查中断状态
避免死等:始终指定合理超时时间
不要传入过长的超时(如 Long.MAX_VALUE),更不要用 0(即刻返回)。生产环境建议设置明确上限(如 30 秒),并配合日志或监控,便于排查卡住的任务。
- 推荐写法:
awaitTermination(30, TimeUnit.SECONDS) - 若超时,记录哪些任务可能未完成(可通过
executor.shutdownNow()返回的List<runnable></runnable>获取未开始执行的队列任务)
补充说明:shutdown() 和 shutdownNow() 的区别
shutdown() 是温和关闭:不接受新任务,让已排队和正在运行的任务自然完成;shutdownNow() 是激进关闭:尝试中断所有正在执行的任务,并清空任务队列,返回未执行的任务列表。二者不可替代,通常组合使用。
- 典型流程:
shutdown()→awaitTermination()→ 超时则shutdownNow()→ 再次awaitTermination() - 注意:即使调用了
shutdownNow(),也无法强制终止忽略中断的死循环任务,需在任务内部主动检查中断状态
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











