在 Java 线程池中,shutdown()
和 shutdownNow()
是用于关闭线程池的两个方法,但它们的行为和效果有显著区别。以下是它们的详细对比:
1. shutdown()
- 行为:
- 平缓地关闭线程池。
- 停止接受新任务,但会继续执行已提交的任务(包括正在执行的任务和队列中等待的任务)。
- 调用后,线程池会进入
SHUTDOWN
状态。
- 适用场景:
- 当你希望线程池完成所有已提交的任务后再关闭时使用。
- 示例:
ExecutorService executor = Executors.newFixedThreadPool(2); executor.execute(() -> System.out.println("任务1")); executor.execute(() -> System.out.println("任务2")); executor.shutdown(); // 停止接受新任务,等待已提交任务完成
2. shutdownNow()
- 行为:
- 立即尝试停止所有正在执行的任务,并停止处理队列中等待的任务。
- 返回一个包含未执行任务的列表(
List<Runnable>
)。 - 调用后,线程池会进入
STOP
状态。 - 通过调用线程的
interrupt()
方法来尝试中断正在执行的任务(如果任务没有响应中断,则无法停止)。
- 适用场景:
- 当你希望立即停止所有任务时使用。
- 示例:
ExecutorService executor = Executors.newFixedThreadPool(2); executor.execute(() -> { try { Thread.sleep(1000); System.out.println("任务1"); } catch (InterruptedException e) { System.out.println("任务1被中断"); } }); executor.execute(() -> System.out.println("任务2")); List<Runnable> notExecutedTasks = executor.shutdownNow(); // 立即停止所有任务 System.out.println("未执行的任务数量: " + notExecutedTasks.size());
主要区别
特性 | shutdown() | shutdownNow() |
---|---|---|
是否接受新任务 | 停止接受新任务 | 停止接受新任务 |
已提交任务的处理 | 继续执行已提交的任务 | 尝试停止所有任务(包括正在执行的任务) |
队列中的任务 | 继续执行队列中的任务 | 清空队列并返回未执行的任务列表 |
线程池状态 | 进入 SHUTDOWN 状态 | 进入 STOP 状态 |
中断线程 | 不会中断线程 | 尝试中断所有线程 |
返回值 | 无返回值 | 返回未执行的任务列表 |
注意事项
- 任务的中断:
shutdownNow()
会尝试中断正在执行的任务,但如果任务没有响应中断(例如没有检查Thread.interrupted()
),任务可能不会停止。
- 线程池的最终状态:
- 调用
shutdown()
或shutdownNow()
后,线程池会进入终止状态(TERMINATED
),但需要调用awaitTermination()
来等待线程池完全关闭。
- 调用
- 任务的中断处理:
- 如果任务需要支持中断,应该在任务中定期检查
Thread.interrupted()
或捕获InterruptedException
。
- 如果任务需要支持中断,应该在任务中定期检查
总结
- 使用
shutdown()
时,线程池会优雅地关闭,确保所有已提交的任务完成。 - 使用
shutdownNow()
时,线程池会立即尝试停止所有任务,适合需要快速关闭的场景。
THE END
暂无评论内容