ExecutorService线程池关闭方式详解
创作时间:
作者:
@小白创作中心
ExecutorService线程池关闭方式详解
引用
CSDN
1.
https://m.blog.csdn.net/weixin_45428910/article/details/145359103
ExecutorService提供了多种关闭线程池的方法,每种方式都有其适用场景和特点。本文将详细介绍这些关闭方式及其区别,并通过示例代码帮助读者更好地理解如何在实际开发中使用它们。
1. 关闭线程池的几种方式
1.1 shutdown()
作用:
- 平缓关闭线程池。
- 停止接受新任务,同时等待已提交的任务(包括正在执行的和队列中的任务)执行完成。
特点:
- 不会强制中断正在运行的线程。
- 可以配合
awaitTermination()
等待线程池完全关闭。
适用场景:
- 程序需要保证已提交任务全部执行完毕。
示例:
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> System.out.println("任务1执行"));
executor.submit(() -> System.out.println("任务2执行"));
executor.shutdown(); // 停止接受新任务
try {
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
System.out.println("线程池未完全关闭");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
1.2 shutdownNow()
作用:
- 强制关闭线程池。
- 尝试中断正在运行的线程,并清空任务队列中的所有待执行任务。
特点:
- 返回未执行的任务列表。
- 线程池中已运行的任务可能无法正常完成。
- 强制中断的任务是否生效,取决于任务是否响应中断(例如,通过检查
Thread.interrupted()
)。
适用场景:
- 需要尽快停止线程池,不关心未完成任务。
示例:
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("任务被中断");
}
});
List<Runnable> unexecutedTasks = executor.shutdownNow(); // 强制关闭
System.out.println("未执行的任务数量: " + unexecutedTasks.size());
1.3 awaitTermination()
作用:
- 配合
shutdown()
使用,用于等待线程池中的任务在指定时间内完成。
特点:
- 如果在指定时间内所有任务都完成,返回
true
;否则返回false
。 - 必须在调用
shutdown()
或shutdownNow()
之后使用。
适用场景:
- 需要阻塞主线程,等待线程池完成所有任务或超时退出。
示例:
executor.shutdown();
try {
boolean terminated = executor.awaitTermination(5, TimeUnit.SECONDS);
if (terminated) {
System.out.println("所有任务完成");
} else {
System.out.println("等待超时,线程池未关闭");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
1.4 isShutdown() 和 isTerminated()
作用:
isShutdown()
:判断线程池是否调用了shutdown()
或shutdownNow()
。isTerminated()
:判断线程池是否已完全终止(即所有任务都已完成)。
特点:
isShutdown()
只能判断是否关闭线程池,不判断任务是否执行完。isTerminated()
确保所有任务执行完毕后返回true
。
适用场景:
用于监控线程池状态。
示例:
executor.shutdown();
System.out.println("是否调用 shutdown(): " + executor.isShutdown());
System.out.println("是否完全终止: " + executor.isTerminated());
2. 关闭方式的区别
3. 使用建议
推荐使用
shutdown()
:在大多数情况下,
shutdown()
是首选,确保线程池内所有任务能够有序完成。避免滥用
shutdownNow()
:只有在必须强制停止任务的场景下使用,并确保任务能够正确处理中断。
结合
awaitTermination()
使用:配合
shutdown()
,为任务提供合理的完成时间,避免主线程提前退出。监控线程池状态:
使用
isShutdown()
和isTerminated()
确保线程池的状态符合预期。
4. 示例:完整演示关闭线程池
import java.util.concurrent.*;
public class ThreadPoolShutdownExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
// 提交任务
for (int i = 1; i <= 5; i++) {
int taskNumber = i;
executor.submit(() -> {
System.out.println(Thread.currentThread().getName() + " 正在执行任务 " + taskNumber);
try {
Thread.sleep(2000); // 模拟任务执行耗时
} catch (InterruptedException e) {
System.out.println("任务 " + taskNumber + " 被中断");
}
});
}
// 关闭线程池
executor.shutdown();
try {
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
System.out.println("任务未完成,强制关闭线程池...");
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
System.out.println("线程池是否完全终止: " + executor.isTerminated());
}
}
通过这些关闭方式的结合,可以根据具体需求选择适合的线程池关闭策略,保证程序的稳定性与效率。
热门推荐
西安今正制药:复方塞隆胶囊治风湿骨病的秘密
“偏头痛”主要与这4个因素有关,如何缓解?
父女情深:单亲爸爸如何克服困难,陪伴女儿成长的感人故事
杜鹃花喜欢阳光吗?具体要怎么养殖?
杜鹃花放室内还是室外养比较好?用什么盆养比较好?
敬酒词怎么说?掌握这几招,大方得体又简单!
GI值(升糖指数)是什么?低GI值的食物对我们有什么好处?
减肥期间甜玉米推荐吃多少
职场人士如何避免酒驾?代驾帮你搞定!
1990年赵本山首登春晚,背后有姜昆助力!
《哪吒之魔童闹海》与《唐探1900》:2025春节档的双子星
史上最强春节档:上海的票房奇迹与产业融合新趋势
人类烹饪的六大层次
桥式运动和侧腿抬高,轻松告别胯痛!
骨关节炎:如何保护你的髋关节?
久坐开车臀部疼痛?一招拉伸快速解决!
春节聚餐饮酒,这些法律误区你必须知道!
冬季聚餐,劝酒出事谁担责?
杨幂红衣双马尾美出圈!38岁状态惊艳众人
酒驾酿悲剧:家庭破碎的惨痛代价
狗狗嗓子有痰?当心是犬窝咳!
心脏介入手术后多久能正常活动
这种神仙早餐搭配“控血糖”又好吃!难怪这么火!
高血压血糖病史下的脑梗患者:科学饮食,守护健康
《红海行动》续作《蛟龙行动》口碑炸裂,是春节档必看硬核特效片
辽宁最有名的七大特色小吃,特别是第六道,可能和你想的不一样
冬季必吃:用土豆淀粉做完美锅包肉
哈尔滨锅包肉大赛:一场传统与创新的美食盛宴
北美五大湖探秘:穿越世界最大淡水湖群的奇幻之旅
湖:地理学名词详解