不能。shutdown()将线程池状态设为SHUTDOWN,此后submit()或execute()会立即抛出RejectedExecutionException,不再接受任何新任务。

shutdown() 后任务还能提交吗?
不能。shutdown() 会将线程池状态设为 SHUTDOWN,此后调用 submit()、execute() 等方法会立即抛出 RejectedExecutionException。这不是“延迟拒绝”,而是立刻失败——这点常被误认为“还能塞几个任务进去”。
- 如果需要继续接受新任务,得用
shutdownNow()(但会中断正在运行的任务,不推荐作为优雅关闭手段)
- 真正的“优雅”是指:已提交但未开始执行的任务继续排队,正在运行的任务允许跑完
- 常见错误是调用
shutdown() 后还盲目重试提交,结果反复触发异常
为什么 shutdown() 不等于线程池立即停止?shutdown() 只是“关闸”,不是“拔电”。它不会中断任何线程,也不会清理队列,只是禁止新任务入场。线程池是否真正空闲,取决于:
- 已在工作队列中的任务是否执行完毕
- 正在运行的线程是否自然结束(无中断、无强制退出)
- 你有没有主动等待它们完成
shutdownNow()(但会中断正在运行的任务,不推荐作为优雅关闭手段)shutdown() 后还盲目重试提交,结果反复触发异常shutdown() 只是“关闸”,不是“拔电”。它不会中断任何线程,也不会清理队列,只是禁止新任务入场。线程池是否真正空闲,取决于:
- 已在工作队列中的任务是否执行完毕
- 正在运行的线程是否自然结束(无中断、无强制退出)
- 你有没有主动等待它们完成
典型疏漏是调用 shutdown() 后直接退出或释放资源,导致部分任务被丢弃(尤其当使用 LinkedBlockingQueue 这类无界队列时,任务可能还在排队中)。
如何确认所有任务真的执行完了?
必须配合 awaitTermination(long timeout, TimeUnit unit) 使用,否则无法知道线程池是否真正终止:
-
awaitTermination() 是阻塞调用,返回 true 表示线程池已终止,false 表示超时后仍活跃
- 超时后若仍需强关,才考虑
shutdownNow(),并手动处理返回的 List(即被取消的待执行任务)
- 示例节选:
executor.shutdown();
try {
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
System.err.println("线程池未正常终止");
}
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
常见陷阱:守护线程、未捕获异常、自定义 ThreadFactory
- 如果线程池里的任务抛出未捕获异常,且没用 Thread.UncaughtExceptionHandler 处理,该工作线程会静默死亡,可能导致任务永远卡住(尤其在线程数 = 核心线程数且队列非空时)
- 使用自定义 ThreadFactory 时,务必确保创建的线程不是守护线程(setDaemon(false)),否则 JVM 可能在主线程退出时直接终止它们,造成任务丢失
- ScheduledThreadPoolExecutor 的 shutdown() 行为与普通线程池一致,但要注意:已调度但未触发的周期任务会被取消,这点容易被忽略
awaitTermination() 是阻塞调用,返回 true 表示线程池已终止,false 表示超时后仍活跃shutdownNow(),并手动处理返回的 List(即被取消的待执行任务)
executor.shutdown();
try {
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
System.err.println("线程池未正常终止");
}
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
Thread.UncaughtExceptionHandler 处理,该工作线程会静默死亡,可能导致任务永远卡住(尤其在线程数 = 核心线程数且队列非空时)
- 使用自定义 ThreadFactory 时,务必确保创建的线程不是守护线程(setDaemon(false)),否则 JVM 可能在主线程退出时直接终止它们,造成任务丢失
- ScheduledThreadPoolExecutor 的 shutdown() 行为与普通线程池一致,但要注意:已调度但未触发的周期任务会被取消,这点容易被忽略
真正难的不是调用 shutdown(),而是判断“什么时候才算安全关机”——这取决于你的任务是否有外部依赖、是否写磁盘、是否发网络请求,以及你愿为等待付出多少时间成本。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











