【线程池】如何判断线程池中的任务执行完毕(三)
目录
前言
1. isTerminated()方法
2. awaitTermination()方法
3.getTaskCount()方法和executor.getCompletedTaskCount()方法结合使用
4.使用CountDownlatch类
前言
通常我们使用线程池的时候,系统处于运行的状态,而线程池本身就是主要为了线程复用,需要线程池跟随系统一直跑起来。
大多数时候,对于我们来说线程池就是一个黑盒,纵然我们可能对线程池的实现,底层原理盘的比老核桃还圆润,但是对于线程池的异常处理、事务处理、上下文传递、以及如何判断线程池中的任务执行状态,我们仍然是不可言状的。无法掌控、无法预测,会在一些细微时候给我们的应用程序带来致命一击。
那么我来聊下以下几种判断线程池中任务是否执行完毕的方式,谁赞成,谁反对。
我们先把线程池启动起来,线程数5个,往线程池中提交10个任务。
基于上面的线程池,开始表演。
1. isTerminated()方法
通过终止线程池 判断线程池中是否终止 来判断任务是否执行完毕 但是一般线程池也不会终止,不推荐使用。
但是,有些个别情况我们确实需要停止线程池,比如系统停止的时候,异常终止的时候,如何优雅的停止线程池不得不来考虑下,在高负荷的系统中,停止线程池好似那狂奔180迈的迈巴赫踩下刹车,能安全平稳的停下来最好不过了。
//终止线程池executor.shutdown();while (!executor.isTerminated()) {try {TimeUnit.MILLISECONDS.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("线程还在执行中");long taskCount = executor.getCompletedTaskCount();System.out.println("完成的任务数:" + taskCount);}
执行结果如下,完成任务数10
2. awaitTermination()方法
使用awaitTermination()方法会阻塞当前线程,等待线程池执行任务,但是呢这个等待的时间是不确定,好似等待约会的女孩化妆,耗时不固定,但等待时间要足够长,缺点就是不可控,不可预测,正如我们的人生一样,茫茫无边际。
如果等待时间足够长,输出是没问题的
try {executor.awaitTermination(10, TimeUnit.SECONDS);long taskCount = executor.getCompletedTaskCount();System.out.println("完成的任务数:" + taskCount);} catch (InterruptedException e) {e.printStackTrace();}
但如果恰好配置的时间不够,我们给配置成1s,就像恋爱时追女孩子的耐心不够,不好意思,你等不完她的化妆时间,注定孤独一生,自然也完成不了所有的任务
可以看到我们在获取任务完成个数的时候只有5条。

3. getTaskCount()方法和executor.getCompletedTaskCount()方法结合使用
while (executor.getTaskCount() != executor.getCompletedTaskCount()) {System.out.println("所有任务数:" + executor.getTaskCount() + ";已完成任务数" + executor.getCompletedTaskCount());}System.out.println("最后已完成的任务数:" + executor.getCompletedTaskCount());

4. 使用CountDownlatch类
很多时候线程池并不专一,喜欢脚踏多个业务船,可能提交多种业务数据,我们只想看到我们提交的业务数据执行情况。
比如下面,我们再提交15条任务给线程池,线程池这家伙可是来着不拒的。
//在业务线程池正在执行上面10条任务的时候,再新提交15条任务,而我们只关注这15条任务该怎么做呢for (int i = 0; i < 15; i++) {int finalI = i;executor.execute(() -> {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("【新提交的任务】" + Thread.currentThread().getName() + " 执行完了第" + finalI + "个任务") ;});}
这个时候我们就可以请求外援,使用CountDownlatch来进行上述代码的改造,通过countDown()方法进行计数,await()方法阻塞等待,对完成的任务进行判断。
CountDownLatch latch = new CountDownLatch(15);for (int i = 0; i < 15; i++) {int finalI = i;executor.execute(() -> {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("【新提交的任务】" + Thread.currentThread().getName() + " 执行完了第" + finalI + "个任务") ;latch.countDown();});}latch.await();System.out.println("新提交的任务执行完成啦");System.out.println("最后已完成的总计任务数:" + executor.getCompletedTaskCount());
5. 手动维护一个线程安全的计数器
比如说JUC包下常见的基于CAS的AtomicInteger类,基于底层的unsafe类,在多线程的情况下依然可以保证线程的安全,我们可以放心的将它在线程池中进行累加,直到累加到和提交的任务数量一致,线程池也就执行完了所有的任务。

6. 使用Future
我们也可以换个路子,提交线程池不适用execute()方法,使用submit()方法,记得使用submit()方法要谨慎些,具体的坑可以参考之前的文章【线程池】换个姿势来看线程池中不一样的阻塞队列(一)_走了一些弯路的博客-CSDN博客


相关文章:
【线程池】如何判断线程池中的任务执行完毕(三)
目录 前言 1. isTerminated()方法 2. awaitTermination()方法 3.getTaskCount()方法和executor.getCompletedTaskCount()方法结合使用 4.使用CountDownlatch类 前言 通常我们使用线程池的时候,系统处于运行的状态,而线程池本身就是主要为了线程复用&…...
Qt/C++编写视频监控系统81-Onvif报警抓图和录像并回放
一、前言 视频监控系统中的图文警情模块,是通过Onvif协议的事件订阅拿到的,通过事件订阅后,设备的各种报警事件比如入侵报警/遮挡报警/越界报警/开关量报警等,触发后都会主动往订阅者发送,而且一般都是会发送两次&…...
浅谈安防视频监控平台EasyCVR视频汇聚平台对于夏季可视化智能溺水安全告警平台的重要性
每年夏天都是溺水事故高发的时期,许多未成年人喜欢在有水源的地方嬉戏,这导致了悲剧的发生。常见的溺水事故发生地包括水库、水坑、池塘、河流、溪边和海边等场所。 为了加强溺水风险的提示和预警,完善各类安全防护设施,并及时发现…...
基于单片机的串行通信发射机设计
一、项目介绍 串行通信是一种常见的数据传输方式,允许将数据以比特流的形式在发送端和接收端之间传输。当前实现基于STC89C52单片机的串行通信发射机,通过红外发射管和接收头实现自定义协议的数据无线传输。 二、系统设计 2.1 单片机选择 在本设计中&…...
MySQL数据库——多表查询(3)-自连接、联合查询、子查询
目录 自连接 查询语法 自连接演示 联合查询 查询语法 子查询 介绍 标量子查询 列子查询 行子查询 表子查询 自连接 通过前面的学习,我们对于连接已经有了一定的理解。而自连接,通俗地去理解就是自己连接自己,即一张表查询多次。…...
day53 动规.p14 子序列
- 1143.最长公共子序列 cpp class Solution { public: int longestCommonSubsequence(string text1, string text2) { vector<vector<int>> dp(text1.size() 1, vector<int>(text2.size() 1, 0)); for (int i 1; i < text1.size(…...
将docker打包成镜像并保存到本地
如果想重装系统,又不想破坏docker里面配好的环境,那么可以将docker镜像打包到本地进行保存。 1. 将docker打包成镜像 命令:docker commit 容器id 镜像名:tag 使用docker ps -a即可查看容器相关信息 docker commit dd25c7c6bf17 zm_cu101:c…...
Harmony数据存储工具类
使用的是mmkv 1、安装mmkv ohpm install @ohos/mmkv2、封装 import{MMKV, SerializeBase} from @ohos/mmkv/*** 数据存储工具类*/ class MMKVUtil{private filePath:string = private cachePath:string = private mmkv:MMKVprivate mmapID:string="MMKV"construct…...
ROS 2官方文档(基于humble版本)学习笔记(一)
ROS 2官方文档(基于humble版本)学习笔记(一) 一、安装ROS 2二、按教程学习1.CLI 工具配置环境使用turtlesim,ros2和rqt安装 turtlesim启动 turtlesim使用 turtlesim安装 rqt使用 rqt重映射关闭turtlesim 由于市面上专门…...
【数据结构】十字链表的画法
十字链表的基本概念 有向边又称为弧 假设顶点 v 指向 w,那么 w 称为弧头,v 称为弧尾 顶点节点采用顺序存储 顶点节点 data:存放顶点的信息firstin:指向以该节点为终点(弧头)的弧节点firstout࿱…...
使用rabbitmq进行支付之后的消息通知
订单服务完成支付后将支付结果发给每一个与订单服务对接的微服务,订单服务将消息发给交换机,由交换机广播消息,每个订阅消息的微服务都可以接收到支付结果. 微服务收到支付结果根据订单的类型去更新自己的业务数据。 相关技术方案 使用消息…...
【100天精通python】Day47:python网络编程_Web开发:web服务器,前端基础以及静态服务器
目录 1 网络编程与web编程 1.1 网络编程 1.2 web编程 1.3 前后端交互的基本原理 2 Web开发基础 2.1 HTTP协议 2.2 Web服务器 2.3 前端基础 2.3.1 HTML(超文本标记语言) 2. 3.2 CSS(层叠样式表) 2.3.3 JavaScript 2.…...
Web框架Beego
beego简介第一个beego项目beego项目结构分析bee 工具简介beego参数配置beego路由设置beego控制器介绍beego获取参数beego ORMbeego orm高级查询beego 原生sql查询beego 模板语法指南beego模板处理...
Kubernetes(K8s)基本环境部署
此处只做学习使用,配置单master环境。 一、环境准备 1、ip主机规划(准备五台新机)>修改各个节点的主机名 注意:关闭防火墙与selinux 节点主机名ip身份joshua1 kubernetes-master.openlab.cn 192.168.134.151masterjoshua2k…...
antd5:form组件底层封装库field-form-1.37.0启动
一开始node版本是18.16.0 npm install发现安装依赖成功 npm start发现启动出错 node:internal/crypto/hash:71this[kHandle] new _Hash(algorithm, xofLen);^Error: error:0308010C:digital envelope routines::unsupportedat new Hash (node:internal/crypto/hash:71:19)…...
深度学习经典检测方法的概述
深度学习经典的检测方法 two-stage(两阶段):Faster-rcnn Mask-Rcnn系列 两阶段(two-stage)是指先通过一个区域提取网络(region proposal network,RPN)生成候选框,再通过…...
viewpager2导致的mViews下标越界问题
viewpager2种在嵌套一个RecyclerView场景:左右滑动,上下滑动,出现mViews为null问题。 //RecyclerView布局为 new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL) 由于使用viewpager2导致布局缓存的销毁,会…...
无涯教程-JavaScript - NORMSDIST函数
NORMSDIST函数替代Excel 2010中的NORM.S.DIST函数。 描述 该函数返回标准正态累积分布函数。分布的平均值为0(零),标准偏差为1。使用此功能代替标准法线区域的表格。 语法 NORMSDIST (z)争论 Argument描述Required/OptionalZThe value for which you want the distributio…...
Mysql查询(SELECT)
基本查询:SELECT FROM SELECT 查询字段 FROM 表名; SELECT * FROM userinfo; 条件查询:用where表示查询条件 SELECT 查询字段 FROM 表名 WHERE 条件; 模糊查询:like %匹配0或多个字符,一般不用左模糊(%放在左边&…...
基于JAVAEE技术的ssm校园车辆管理系统源码和论文
基于JAVAEE技术的ssm校园车辆管理系统源码和论文105 开发工具:idea 数据库mysql5.7 数据库链接工具:navcat,小海豚等 技术:ssm 1.选题背景和意义 背景: 随着第二次工业革命后,内燃机的发明与完善,解…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
