java 等待线程池结束_等待线程池中任务执行完毕做优雅关闭
背景
在Java开发中,如果涉及多线程,会经常使用到线程池,本期不额外讲述线程池本身相关的东西。考虑一种场景,如果我们提交给线程池的任务都相对比较耗时,而在任务启动运行后,如果后续有需求的变更,要重新部署业务。
这时,需要关闭当前的执行实例或者重启,如果直接kill实例而任务又包含多个复杂的逻辑,可能导致一些非预期的后果。因此,类似情况下,需要等线程池中已有任务尽量执行完毕,来避免带来意料以外的问题。当然本身的
threadPoolExecutor是带有相关处理机制的,下面就介绍对应方法以及使用。
线程池停止
threadPoolExecutor 提供了两个线程池停止方法shutdown(),shutdownNow()。首先shutdown()将状态转换为shutdown,方法不会阻塞,没有返回值;shutdownNow()将状态转换为stop,方法不会阻塞,返回线程池队列中等待执行的任务列表。如果要等待任务执行完毕,就要和另一个方法配合实现,即awaitTermination()。如下代码,后面做解释说明。
代码
static ThreadPoolExecutor executorService = new ThreadPoolExecutor(5, 5, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
@Test
public void executorTest() throws InterruptedException {
//用来监控线程池的执行状态,注意初始化用ThreadPoolExecutor,非executorService
Thread t = new Thread(() -> {
while (true) {
try {
System.out.println(executorService);
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
//记录执行时间
long start = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
int x = i;
CompletableFuture.runAsync(() -> {
try {
System.out.println("running..." + x);
if (x == 7) {
TimeUnit.SECONDS.sleep(20);
}else {
TimeUnit.SECONDS.sleep(5);
}
} catch (Exception e) {
e.printStackTrace();
}
}, executorService).toCompletableFuture().whenComplete((aVoid, throwable) -> {
//每个任务执行完成的需要的时间
System.out.println(System.currentTimeMillis() - start);
});
}
//执行shutdown
if (!executorService.isShutdown()) {
executorService.shutdown();
System.out.println("start shutdown ...");
//等待执行结束
executorService.awaitTermination(2, TimeUnit.MINUTES);
}
}
执行结果
java.util.concurrent.ThreadPoolExecutor@1866f339[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
running...0
running...1
running...2
running...3
running...4
start shutdown ...
java.util.concurrent.ThreadPoolExecutor@1866f339[Shutting down, pool size = 5, active threads = 5, queued tasks = 5, completed tasks = 0]
5003
running...5
5004
5004
5004
running...7
running...6
5004
running...8
running...9
java.util.concurrent.ThreadPoolExecutor@1866f339[Shutting down, pool size = 5, active threads = 5, queued tasks = 0, completed tasks = 5]
java.util.concurrent.ThreadPoolExecutor@1866f339[Shutting down, pool size = 5, active threads = 5, queued tasks = 0, completed tasks = 5]
10003
10005
10005
10005
java.util.concurrent.ThreadPoolExecutor@1866f339[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 9]
java.util.concurrent.ThreadPoolExecutor@1866f339[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 9]
java.util.concurrent.ThreadPoolExecutor@1866f339[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 9]
java.util.concurrent.ThreadPoolExecutor@1866f339[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 9]
java.util.concurrent.ThreadPoolExecutor@1866f339[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 9]
25005
解析
这里使用了awaitTermination和shutdown来配合,可以看到最终的执行时间是25s,即一般线程5秒和最长线程20s的和,这里用id=7的为最长,可以实验下,如果改成id=4为最长执行时间,因为4<5,5是核心线程池
数,id=4就属于所有任务前半部分(先提交的部分),所有任务最长执行时间约20s。有人会问,为什么不用shutdownNow,因为shutdownNow会将所有的执行线程设置为interrupt,包括正在活跃的。而shutdown只将空闲等待状态的线程做状态变更,不会影响正在执行的。
可以试验下,如果改成shutdownNow,后续任务是没法执行成功的。 其中sleep会被interrupt打断。
总结
以上就是本期的内容,注意awaitTermination,有超时设置,可以避免一直阻塞,实现是用condition的waitNanos, 同时一定要配合shutdown使用,避免不必要的等待时间,意思就是先shutdown然后再awatiTermination。
java 等待线程池结束_等待线程池中任务执行完毕做优雅关闭相关推荐
- linux 查询线程是否结束_批量随机键值查询测试
[摘要] 当数据量巨大时,使用大批量随机键值集获取对应记录集合,不仅仅考验数据库软件本身,更在于程序员对数据的理解!如何在硬件资源有限的情况下将性能发挥到极致?点击:批量随机键值查询测试,来乾学院一探 ...
- python两个线程交替打印_三线程按顺序交替打印ABC的四种方法
建立三个线程A.B.C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印. 二.Synchroni ...
- python线程异常中断_中断线程
如果线程需要执行一个长时间任务,就可能需要能中断线程.中断线程就是其他线程给该线程发一个信号,该线程收到信号后结束执行run()方法,使得自身线程能立刻结束运行. 我们举个栗子:假设从网络下载一个10 ...
- java scanner以回车结束_大佬看了直呼内行,你当初Java刚入门是否也是这样写代码?...
1.集成开发环境 IDEA是一个专门针对Java的集成开发工具(IDE),由Java语言编写.所以,需要有JRE运行环境并配置好环境变量.它可以极大地提升我们的开发效率.可以自动编译,检查错误. 2. ...
- 平流式隔油池计算_广州隔油池清理公司讲述清理隔油池程序和标准_新闻中心...
广州隔油池清理公司讲述清理隔油池程序和标准_隔油池清理,清理隔油池,隔油池清理方案,隔油池清理公司,隔油池清理价格 1.?隔油池/内污水油每月定期清理一次,若检查发现污水油超标以致可能影响隔油池有效性 ...
- java低层源码_如何查看javaJDK中底层源码
展开全部 在初次使用java时,往往我32313133353236313431303231363533e4b893e5b19e31333363393735们对最基本的java类会忽略对其内部基本的实现 ...
- java 等待线程池结束_如何等待java线程池中所有任务完成
一.等待线程池所有线程完成: 有时候我们需要等待java thread pool中所有任务完成后再做某些操作,如想要等待所有任务完成,仅需调用threadPool.awaitTermination() ...
- java修改线程池名称_自定义线程池的名称(ThreadPoolExecutor)
目的:有时候为了快速定位出现错误的位置,在采用线程池时我们需要自定义线程池的名称. 1.创建ThreadFactory(ThreadPoolExecutor默认采用的是DefaultThreadFac ...
- java线程报时代码_什么?一个核同时执行两个线程?
CPU里的时间 在我所在的CPU这座工厂里,时间的概念有些不太一样.工厂大门外的中央广场上挂着一个大大的钟表,整个计算机世界里的居民能够掐着时间过日子全都仰仗它,你们人类把它叫做晶振. 这个钟表每隔6 ...
最新文章
- Occupancy Networks:基于学习函数空间的三维重建表示方法
- charts混合使用 elementui和e_vue模块化(echart+element ui)
- 公式没有编号_知乎公式编辑器的一些小技巧 amp; 使用规范
- 从 25 倍稀释下的蘑菇街期权说起
- python中常用的序列化模块_Python中的序列化和反序列化
- php5中Xdebug配置安装步骤介绍
- 无法全新安装_好墙板更需好安装:护墙板安装新方法
- H264编码 封装成MP4格式 视频流 RTP封包
- oracle_Grid Infrastructure 启动的五大问题
- 绩效管理这样做,成本减半,员工叫好!
- 零基础学python大概要多久-怎么自学python,大概要多久?
- Power Query 系列 (04) - 从 Web 导入数据
- voip和rtc_VOIP的发展进化史
- 蓝牙BT射频测试(转发)
- 数据结构WSADATA
- DataSource
- csdn前200的大牛
- 微信电子健康卡开放平台接口对接
- 编程题——真题训练一(WYYX)
- 配置fly.js请求