锁定网站导航栏怎么去优化关键词
Java 线程池中 shutdown
与 shutdownNow
的区别
- 核心行为差异
| 方法 | 行为描述 |
|----------------|----------------------------------------------------------------------------|
|shutdown
| 平缓关闭线程池:
1. 停止接受新任务。
2. 已提交的任务(包括队列中的任务)会继续执行完成。 |
|shutdownNow
| 强制关闭线程池:
1. 停止接受新任务。
2. 尝试中断正在执行的任务。
3. 清空任务队列,并返回未执行的任务列表。 |
- 线程中断机制
-
shutdown
:- 不中断任何线程,正在执行的任务会继续运行直到完成。
- 适用于需要确保所有已提交任务完整执行的场景(如数据持久化)。
-
shutdownNow
:- 向所有工作线程发送中断信号(调用
Thread.interrupt()
)。 - 任务是否终止取决于代码逻辑:
- 若任务未检查中断状态(如未捕获
InterruptedException
),可能无法终止。 - 示例:一个循环任务中未调用
Thread.currentThread().isInterrupted()
,即使调用shutdownNow
,任务仍会继续运行。
- 若任务未检查中断状态(如未捕获
- 向所有工作线程发送中断信号(调用
- 任务队列处理
| 方法 | 队列处理 | 返回值 |
|----------------|----------------------------------------------------------------------------|------------------------------|
|shutdown
| 继续执行队列中所有任务。 | 无返回值。 |
|shutdownNow
| 移除并丢弃队列中所有未执行的任务,返回这些任务的列表(List<Runnable>
)。 | 返回未执行任务的列表。 |
- 线程池状态变化
-
shutdown
:- 将线程池状态从
RUNNING
改为SHUTDOWN
。 - 最终状态会过渡到
TERMINATED
(需所有任务执行完毕)。
- 将线程池状态从
-
shutdownNow
:- 将线程池状态从
RUNNING
改为STOP
。 - 最终状态过渡到
TERMINATED
(无论任务是否全部完成)。
- 将线程池状态从
- 适用场景
| 方法 | 典型场景 |
|----------------|----------------------------------------------------------------------------|
|shutdown
| 需要确保所有任务完整执行(如数据库批量写入、日志归档)。 |
|shutdownNow
| 紧急终止线程池(如服务宕机前快速释放资源,或处理死锁任务)。 |
实战建议
-
优雅关闭的最佳实践:
- 先调用
shutdown
,再通过awaitTermination
等待任务完成。 - 若超时未完成,再调用
shutdownNow
强制终止。
executor.shutdown(); try {if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow(); // 超时后强制终止 } } catch (InterruptedException e) {executor.shutdownNow(); }
- 先调用
-
任务代码的容错设计:
- 在任务中定期检查中断状态,确保能响应
shutdownNow
。
public void run() {while (!Thread.currentThread().isInterrupted()) {// 执行任务逻辑 } }
- 在任务中定期检查中断状态,确保能响应
-
监控与日志:
- 记录
shutdownNow
返回的未执行任务列表,用于故障恢复或重试。
- 记录
扩展:源码级逻辑
shutdown
:- 仅修改线程池状态为
SHUTDOWN
,后续执行完队列任务后触发terminate()
。
- 仅修改线程池状态为
shutdownNow
:- 修改状态为
STOP
,中断所有工作线程,并清空队列。 - 源码片段:
public List<Runnable> shutdownNow() {List<Runnable> tasks;final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {checkShutdownAccess();advanceRunState(STOP); // 状态改为STOP interruptWorkers(); // 中断所有线程 tasks = drainQueue(); // 清空队列并返回未执行任务 } finally {mainLock.unlock();}tryTerminate();return tasks; }
- 修改状态为
总结
shutdown
是“礼貌告别”,确保任务善后。shutdownNow
是“强制清场”,适合紧急场景,但依赖任务代码的健壮性。- 关键选择点:是否需要保留未执行任务?能否容忍任务中途终止?