前言
🍊缘由
Java线程池优雅停止:比分手还难的事,让我来全搞定
想象一下,关闭线程池就像和前任分手——既要干脆利落不留后患,又得顾及对方(任务)情绪别搞崩盘。你试过强行拔电源式关机吗?那可比"拉黑删除"还粗暴,轻则数据丢失资金对账差百万,重则文件损坏系统崩溃老板连夜报警!
🐣闪亮主角
大家好,我是JavaDog程序狗。
今天手把手教你如何像处理渣男/渣女一样优雅地关线程池,保证项目不翻车!
优雅停机三要素:温柔拒绝新客(shutdown)→耐心送走旧客(await)→强制清场备案(shutdownNow)
正文
🎯主要目标
1.线程池是什么
2.为什么要优雅停止线程池
3.线程池优雅停止的核心方法有哪些
4.实际业务场景中如何使用线程池优雅停止
5.代码示例展示线程池优雅停止
🍪目标讲解
一.线程池是什么?
1.白话理解
线程池就像是一个线程的“池子”,里面预先创建了一些线程。当有任务提交时,线程池会从池子中取出一个空闲的线程来执行任务。如果池子中没有空闲线程,任务就会被放到队列中等待。这样可以避免频繁地创建和销毁线程,提高系统的性能。
线程池就像你的恋爱对象:
- 核心线程:天天粘着你的“正经男友/女友”
- 最大线程:节日突击出现的“临时男友/女友”
- 任务队列:你们没吃完的火锅,总得吃完再散!
- 拒绝策略:TA突然说“分手吧”,但你还有99个约会没处理……
2.官方解释
官网解释:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadPoolExecutor.html
在Java中,线程池是通过ExecutorService
接口及其实现类来实现的。常见的线程池实现类有ThreadPoolExecutor
和ScheduledThreadPoolExecutor
等。
二.为什么要优雅停止线程池?
想象一下,你正在玩一款游戏,突然游戏崩溃了,你的进度还没保存,是不是很崩溃?线程池也是一样,如果不优雅地停止线程池,正在执行的任务可能会被强制中断,导致数据丢失或者系统出现异常。
1.避免数据丢失
如果线程正在处理一些重要的数据,突然被中断,这些数据可能就会丢失。比如,一个线程正在将数据写入数据库,还没写完就被中断了,那么数据库中的数据就可能不完整。
2.保证系统稳定性
不优雅地停止线程池可能会导致系统出现一些不可预知的问题。比如,线程池中的线程可能会持有一些资源,如文件句柄、网络连接等,如果不优雅地停止,这些资源可能无法被正确释放,从而导致系统资源泄漏。
三.线程池优雅停止的核心方法有哪些?
1.shutdown()方法
shutdown()
方法就像是给线程池里的工人们发了一个通知,告诉他们“大家把手上的活干完就可以下班啦”。调用这个方法后,线程池会拒绝接受新的任务,但是会继续执行已经提交的任务。
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 提交一些任务
executorService.submit(() -> {
// 任务逻辑
});
// 调用shutdown()方法
executorService.shutdown();
- 优点:给线程池发分手短信:“以后不联系了,但今天的约会我全认!”
- 缺点:如果TA是妈宝男/妈宝女,死活赖着不走怎么办?
2.shutdownNow()方法
shutdownNow()
方法就像是给线程池里的工人们下了一道紧急命令,“别干了,马上都给我下班”。调用这个方法后,线程池会尝试中断正在执行的任务,并返回那些还未开始执行的任务列表。
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 提交一些任务
executorService.submit(() -> {
// 任务逻辑
});
// 调用shutdownNow()方法
List<Runnable> tasks = executorService.shutdownNow();
- 优点:直接拉黑线程池,任务列表清空比删微信更快!
- 缺点:未完成任务直接变成“幽灵订单”,数据库连接池连夜报警!
3.awaitTermination()方法
awaitTermination()
方法就像是在门口等着工人们下班。它会阻塞当前线程,直到线程池中的所有任务都执行完毕或者达到指定的超时时间。
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 提交一些任务
executorService.submit(() -> {
// 任务逻辑
});
// 调用shutdown()方法
executorService.shutdown();
try {
// 等待线程池中的任务执行完毕,最多等待10秒
if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
// 如果超时还没执行完,调用shutdownNow()方法强制停止
executorService.shutdownNow();
}
} catch (InterruptedException e) {
// 处理中断异常
executorService.shutdownNow();
}
四.实际业务场景中如何使用线程池优雅停止?
1.电商系统中的订单处理
在电商系统中,当用户下单后,系统会有一系列的任务需要处理,如扣减库存、生成物流信息等。这些任务可以使用线程池来并行处理。当系统要关闭时,就需要优雅地停止线程池,以确保所有的订单任务都能正确处理完毕。
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 模拟用户下单
executorService.submit(() -> {
// 扣减库存
});
executorService.submit(() -> {
// 生成物流信息
});
// 系统关闭时,优雅停止线程池
executorService.shutdown();
try {
if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
}
2.数据分析系统中的数据处理
在数据分析系统中,需要对大量的数据进行处理和分析。这些任务可以使用线程池来提高处理效率。当数据分析任务完成后,需要优雅地停止线程池,以释放系统资源。
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 提交数据处理任务
executorService.submit(() -> {
// 数据处理逻辑
});
// 任务完成后,优雅停止线程池
executorService.shutdown();
try {
if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
}
五.代码示例展示线程池优雅停止
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadPoolGracefulShutdownExample {
public static void main(String[] args) {
// 创建一个固定大小的线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 提交一些任务
for (int i = 0; i < 10; i++) {
final int taskId = i;
executorService.submit(() -> {
try {
System.out.println("Task " + taskId + " is running.");
Thread.sleep(1000);
System.out.println("Task " + taskId + " is completed.");
} catch (InterruptedException e) {
System.out.println("Task " + taskId + " is interrupted.");
}
});
}
// 调用shutdown()方法
executorService.shutdown();
try {
// 等待线程池中的任务执行完毕,最多等待10秒
if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
// 如果超时还没执行完,调用shutdownNow()方法强制停止
executorService.shutdownNow();
}
} catch (InterruptedException e) {
// 处理中断异常
executorService.shutdownNow();
}
System.out.println("ThreadPool is gracefully shutdown.");
}
}
🍈猜你想问
如何与狗哥联系进行探讨
关注公众号【JavaDog程序狗】
公众号回复【入群】或者【加入】,便可成为【程序员学习交流摸鱼群】的一员,问题随便问,牛逼随便吹,目前群内已有超过380+个小伙伴啦!!!
2.踩踩狗哥博客
里面有狗哥的私密联系方式呦 😘
大家可以在里面留言,随意发挥,有问必答
🍯猜你喜欢
文章推荐
【实操】Spring Cloud Alibaba AI,阿里AI这不得玩一下(含前后端源码)
【项目实战】SpringBoot+uniapp+uview2打造H5+小程序+APP入门学习的聊天小项目