Java多种方法实现等待所有子线程完成再继续执行
简介
在现实世界中,我们常常需要等待其它任务完成,才能继续执行下一步。Java实现等待子线程完成再继续执行的方式很多。我们来一一查看一下。
Thread的join方法
该方法是Thread提供的方法,调用join()时,会阻塞主线程,等该Thread完成才会继续执行,代码如下:
private static void threadJoin() {List<Thread> threads = new ArrayList<>();for (int i = 0; i < NUM; i++) {Thread t = new Thread(new PkslowTask("Task " + i));t.start();threads.add(t);}threads.forEach(t -> {try {t.join();} catch (InterruptedException e) {throw new RuntimeException(e);}});System.out.println("threadJoin Finished All Tasks...");}
结果:
Task 6 is running
Task 9 is running
Task 3 is running
Task 4 is running
Task 7 is running
Task 0 is running
Task 2 is running
Task 1 is running
Task 5 is running
Task 8 is running
Task 1 is completed
Task 8 is completed
Task 6 is completed
Task 4 is completed
Task 3 is completed
Task 0 is completed
Task 7 is completed
Task 9 is completed
Task 2 is completed
Task 5 is completed
threadJoin Finished All Tasks...
CountDownLatch
CountDownLatch是一个很好用的并发工具,初始化时要指定线程数,如10。在子线程调用countDown()时计数减1。直到为0时,await()方法才不会阻塞。代码如下:
private static void countDownLatch() {CountDownLatch latch = new CountDownLatch(NUM);for (int i = 0; i < NUM; i++) {Thread t = new Thread(() -> {System.out.println("countDownLatch running...");try {Thread.sleep(1000);System.out.println("countDownLatch Finished...");latch.countDown();} catch (InterruptedException e) {throw new RuntimeException(e);}});t.start();}try {latch.await();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("countDownLatch Finished All Tasks...");
}
结果:
countDownLatch running...
countDownLatch running...
countDownLatch running...
countDownLatch running...
countDownLatch running...
countDownLatch running...
countDownLatch running...
countDownLatch running...
countDownLatch running...
countDownLatch running...
countDownLatch Finished...
countDownLatch Finished...
countDownLatch Finished...
countDownLatch Finished...
countDownLatch Finished...
countDownLatch Finished...
countDownLatch Finished...
countDownLatch Finished...
countDownLatch Finished...
countDownLatch Finished...
countDownLatch Finished All Tasks...
CyclicBarrier
CyclicBarrier与CountDownLatch类似,但CyclicBarrier可重置,可重用。代码如下:
private static void cyclicBarrier() {CyclicBarrier barrier = new CyclicBarrier(NUM + 1);for (int i = 0; i < NUM; i++) {Thread t = new Thread(() -> {System.out.println("cyclicBarrier running...");try {Thread.sleep(1000);System.out.println("cyclicBarrier Finished...");barrier.await();} catch (InterruptedException | BrokenBarrierException e) {throw new RuntimeException(e);}});t.start();}try {barrier.await();} catch (InterruptedException | BrokenBarrierException e) {throw new RuntimeException(e);}System.out.println("cyclicBarrier Finished All Tasks...");
}
结果:
cyclicBarrier running...
cyclicBarrier running...
cyclicBarrier running...
cyclicBarrier running...
cyclicBarrier running...
cyclicBarrier running...
cyclicBarrier running...
cyclicBarrier running...
cyclicBarrier running...
cyclicBarrier running...
cyclicBarrier Finished...
cyclicBarrier Finished...
cyclicBarrier Finished...
cyclicBarrier Finished...
cyclicBarrier Finished...
cyclicBarrier Finished...
cyclicBarrier Finished...
cyclicBarrier Finished...
cyclicBarrier Finished...
cyclicBarrier Finished...
cyclicBarrier Finished All Tasks...
executorService.isTerminated()
ExecutorService调用shutdown()方法后,可以通过方法isTerminated()来判断任务是否完成。代码如下:
private static void executeServiceIsTerminated() {ExecutorService executorService = Executors.newFixedThreadPool(THREADS);IntStream.range(0, NUM).forEach(i -> executorService.execute(new PkslowTask("Task " + i)));executorService.shutdown();while (!executorService.isTerminated()) {//waiting...}System.out.println("executeServiceIsTerminated Finished All Tasks...");}
结果:
Task 0 is running
Task 2 is running
Task 1 is running
Task 3 is running
Task 4 is running
Task 0 is completed
Task 2 is completed
Task 5 is running
Task 4 is completed
Task 7 is running
Task 3 is completed
Task 1 is completed
Task 8 is running
Task 6 is running
Task 9 is running
Task 5 is completed
Task 9 is completed
Task 7 is completed
Task 6 is completed
Task 8 is completed
executeServiceIsTerminated Finished All Tasks...
executorService.awaitTermination
executorService.awaitTermination方法会等待任务完成,并给一个超时时间,代码如下:
private static void executeServiceAwaitTermination() {ExecutorService executorService = Executors.newFixedThreadPool(THREADS);IntStream.range(0, NUM).forEach(i -> executorService.execute(new PkslowTask("Task " + i)));executorService.shutdown();try {if (!executorService.awaitTermination(1, TimeUnit.MINUTES)) {executorService.shutdownNow();}} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("executeServiceAwaitTermination Finished All Tasks...");
}
结果:
Task 0 is running
Task 1 is running
Task 2 is running
Task 3 is running
Task 4 is running
Task 0 is completed
Task 5 is running
Task 1 is completed
Task 4 is completed
Task 7 is running
Task 3 is completed
Task 8 is running
Task 2 is completed
Task 9 is running
Task 6 is running
Task 5 is completed
Task 7 is completed
Task 9 is completed
Task 8 is completed
Task 6 is completed
executeServiceAwaitTermination Finished All Tasks...
executorService.invokeAll
使用invokeAll提交所有任务,代码如下:
private static void executeServiceInvokeAll() {ExecutorService executorService = Executors.newFixedThreadPool(THREADS);List<Callable<Void>> tasks = new ArrayList<>();IntStream.range(0, NUM).forEach(i -> tasks.add(new PkslowTask("Task " + i)));try {executorService.invokeAll(tasks);} catch (InterruptedException e) {throw new RuntimeException(e);}executorService.shutdown();System.out.println("executeServiceInvokeAll Finished All Tasks...");
}
结果:
Task 1 is running
Task 2 is running
Task 0 is running
Task 3 is running
Task 4 is running
Task 1 is completed
Task 3 is completed
Task 0 is completed
Task 2 is completed
Task 4 is completed
Task 8 is running
Task 5 is running
Task 6 is running
Task 9 is running
Task 7 is running
Task 8 is completed
Task 5 is completed
Task 6 is completed
Task 9 is completed
Task 7 is completed
executeServiceInvokeAll Finished All Tasks...
ExecutorCompletionService
ExecutorCompletionService通过take()方法,会返回最早完成的任务,代码如下:
private static void executorCompletionService() {ExecutorService executorService = Executors.newFixedThreadPool(10);CompletionService<String> service = new ExecutorCompletionService<>(executorService);List<Callable<String>> callables = new ArrayList<>();callables.add(new DelayedCallable(2000, "2000ms"));callables.add(new DelayedCallable(1500, "1500ms"));callables.add(new DelayedCallable(6000, "6000ms"));callables.add(new DelayedCallable(2500, "2500ms"));callables.add(new DelayedCallable(300, "300ms"));callables.add(new DelayedCallable(3000, "3000ms"));callables.add(new DelayedCallable(1100, "1100ms"));callables.add(new DelayedCallable(100, "100ms"));callables.add(new DelayedCallable(100, "100ms"));callables.add(new DelayedCallable(100, "100ms"));callables.forEach(service::submit);for (int i = 0; i < NUM; i++) {try {Future<String> future = service.take();System.out.println(future.get() + " task is completed");} catch (InterruptedException | ExecutionException e) {throw new RuntimeException(e);}}System.out.println("executorCompletionService Finished All Tasks...");executorService.shutdown();awaitTerminationAfterShutdown(executorService);
}
这里不同任务的时长是不一样的,但会先返回最早完成的任务:
2000ms is running
2500ms is running
300ms is running
1500ms is running
6000ms is running
3000ms is running
1100ms is running
100ms is running
100ms is running
100ms is running
100ms is completed
100ms is completed
100ms task is completed
100ms task is completed
100ms is completed
100ms task is completed
300ms is completed
300ms task is completed
1100ms is completed
1100ms task is completed
1500ms is completed
1500ms task is completed
2000ms is completed
2000ms task is completed
2500ms is completed
2500ms task is completed
3000ms is completed
3000ms task is completed
6000ms is completed
6000ms task is completed
executorCompletionService Finished All Tasks...
代码
代码请看GitHub: https://github.com/LarryDpk/pkslow-samples
相关文章:
Java多种方法实现等待所有子线程完成再继续执行
简介 在现实世界中,我们常常需要等待其它任务完成,才能继续执行下一步。Java实现等待子线程完成再继续执行的方式很多。我们来一一查看一下。 Thread的join方法 该方法是Thread提供的方法,调用join()时,会阻塞主线程࿰…...
制造企业数字化工厂建设步骤的建议
随着工业4.0、中国制造2025的深度推进,越来越多的制造企业开始迈入智能制造的领域,那数字工厂要从何入手呢? 数字工厂规划的核心,也正是信息域和物理域这两个维度,那就从这两个维度来进行分析,看如何进行数…...
网上鲜花交易平台,可运行
文章目录项目介绍一、项目功能介绍1、用户模块主要功能包括:2、商家模块主要功能包括:3、管理员模块主要功能包括:二、部分页面展示1、用户模块部分功能页面展示2、商家模块部分功能页面展示3、管理员模块部分功能页面展示三、部分源码四、底…...
【实战】用 Custom Hook + TS泛型实现 useArray
文章目录一、题目二、答案(非标准)三、关键知识点1.Custom Hook关键点案例useMountuseDebounce2.TS 泛型关键点一、题目 完善自定义 Hook —— useArray ,使其能够完成 tryUseArray 组件中测试的功能: 入参:数组返回…...
【LeetCode】剑指 Offer(18)
目录 题目:剑指 Offer 35. 复杂链表的复制 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 写在最后: 题目:剑指 Offer 35. 复杂链…...
Kubernetes节点运行时从Docker切换到Containerd
由于k8s将于1.24版本弃用dockershim,所以最近在升级前把本地的k8s切换到了Containerd运行时,目前我的k8s版本是1.22.5,一个master,二个Node的配置,以下做为一个操作记录日志整理,其它可以参考官网文档。 在…...
【编程基础之Python】12、Python中的语句
【编程基础之Python】12、Python中的语句Python中的语句赋值语句条件语句循环语句for循环while循环continue语句break语句continue与break的区别函数语句pass语句异常处理语句结论Python中的语句 Python是一种高级编程语言,具有简单易学的语法,适用于各…...
android h5餐饮管理系统myeclipse开发mysql数据库编程服务端java计算机程序设计
一、源码特点 android h5餐饮管理系统是一套完善的WEBandroid设计系统,对理解JSP java,安卓app编程开发语言有帮助(系统采用web服务端APP端 综合模式进行设计开发),系统具有完整的源代码和数据库,系统主要…...
容易混淆的嵌入式(Embedded)术语
因为做嵌入式开发工作虽然跳不出电子行业,但还是能接触到跨度较大的不同行当,身处不同的圈子。诸如医疗,银行,车载,工业;亦或者手机,PC,专用芯片;甚至可能横跨系统开发、…...
Nodejs 中 JSON 和 YAML 互相转换
JSON 转换成 YAML 1. 安装 js-yaml 库: npm install js-yaml2. 在程序中引入依赖库 const yaml require(js-yaml);3. 创建一个 js 对象, 代表 json 数据 const jsonData {name: John,age: 30,city: New York };4. 使用 yaml.dump() 把 js 对象转换成 YAML, 返回 YAML 字符…...
C++入门教程||C++ 修饰符类型||C++ 存储类
C 修饰符类型 C 允许在 char、int 和 double 数据类型前放置修饰符。修饰符用于改变基本类型的含义,所以它更能满足各种情境的需求。 下面列出了数据类型修饰符: signedunsignedlongshort 修饰符 signed、unsigned、long 和 short 可应用于整型&#…...
Android开发面试:Java知识答案精解
目录 Java 集合 集合概述 HashMap ConcurrentHashMap 泛型 反射 注解 IO流 异常、深浅拷贝与Java8新特性 Java异常 深浅拷贝 Java8新特性 并发 线程 线程池 锁 volatile JVM 内存区域 内存模型 类加载机制 垃圾回收机制 如何判断对象已死 Java 集合 …...
Windows上一款特别好用的画图软件
安装 废话不多说,打开windows的应用商店,搜索draw.io,点击获取即可。 画图 draw.io的布局左边是各种图形组件,中间是画布,右边是属性设置,文件扩展名是.drawio。 点击左边列表中的图形可以将它添加到画…...
html--学习
javascrapt交互,网页控制JavaScript:改变 HTML 图像本例会动态地改变 HTML <image> 的来源(src):点亮灯泡<script>function changeImage() {elementdocument.getElementById(myimage) #内存变量࿰…...
关于递归处理,应该怎么处理,思路是什么?
其实问题很简单,就是想要循环遍历整个data对象,来实现所有name转成label,但是想到里面还有children属性,整个children里面可能还会嵌套很多很多的name,如此循环,很难搞,知道使用递归,…...
重磅!牛客笔试客户端可防ChatGPT作弊
上线俩月,月活过亿。爆火的ChatGPT能代写文,撕代码,善玩梗,秒答题,几乎“无所不能”,争议也随之而来。调查显示,截至2023年1月,美国89%的大学生利用ChatGPT应付作业,53%的…...
春季训练营 | 前端+验证直通车-全实操项目实践,履历加成就业无忧
“芯动的offer”是2023年E课网联合企业全新推出集训培优班(线下),针对有一定基础(linux、verilog、uvm等)在校学生以及想要通过短时间的学习进入到IC行业中的转行人士,由资深IC设计工程师带教,通…...
2.详解URL
文章目录视图函数1.1endpoint简介1.2 装饰器注册路由源码浅析1.3 另一种注册路由的方式---app.add_url_rule()1.4 视图函数中添加自定义装饰器2 视图类2.1 视图类的基本写法3 详细讲解注册路由的参数3.1常用的参数3.2不常用的参数(了解)视图函数 1.1endpoint简介 endpint参数…...
Android特别的数据结构(二)ArrayMap源码解析
1. 数据结构 public final class ArrayMap<K,V> implements Map<K,V> 由两个数组组成,一个int[] mHashes用来存放Key的hash值,一个Object[] mArrays用来连续存放成对的Key和ValuemHashes数组按非严格升序排列初始默认容量为0减容ÿ…...
减少if else
1. 三目运算符 可以理解为条件 ?结果1 : 结果2 里面的?号是格式要求。也可以理解为条件是否成立,条件成立为结果1,否则为结果2。 实例: public String handle(int code) {if (code 1) {return "success";} else {return &quo…...
硕士毕业论文常见的排版小技巧
word排版陆续更新吧,更具我所遇到的一些小问题,总结上来 文章目录1.避免题注(图或者表的标题)与图或表格分不用页注意点:光标移动到表的题注后面2.设置论文的页眉关键点:需要将每一章节末尾,都要…...
JAVA开发(数据类型String和HasMap的实现原理)
在JAVA开发中,使用最多的数据类型恐怕是String 和 HasMap两种数据类型。在开发的过程中我们每天都使用的不亦乐乎。但是相信很多人都没有考虑过String数据类型的实现原理或者说是在数据结构中的存储原理,还有一个就是是HashMap,也很少有人去了…...
Hbase 映射到Hive
目录 一、环境配置修改 关闭掉hbase,zookeeper和hive服务 进入hive312/conf 修改hive-site.xml配置, 在代码最后添加配置 将hbase235的jar包全部拷贝到hive312的lib目录,并且所有的是否覆盖信息全部输入n,不覆盖 查看hive312下…...
14_MySQL视图
1. 常见的数据库对象2. 视图概述2.1 使用视图的好处视图一方面可以帮我们使用表的一部分而不是所有的表,另一方面也可以针对不同的用户制定不同的查询视图。比如,针对一个公司的销售人员,我们只想给他看部分数据,而某些特殊的数据…...
做程序界中的死神,斩魂刀始解
标题解读:标题中的死神,是源自《死神》动漫里面的角色,斩魂刀是死神的武器,始解是斩魂刀的初始解放形态,卐解是斩魂刀的觉醒解放形态,也是死神的大招。意旨做程序界中程序员的佼佼者,一步一步最…...
顺序表——“数据结构与算法”
各位CSDN的uu们你们好呀,今天小雅兰的内容是数据结构与算法里面的顺序表啦,在我看来,数据结构总体上是一个抽象的东西,关键还是要多写代码,下面,就让我们进入顺序表的世界吧 线性表 顺序表 线性表 线性表&…...
嵌入式Linux从入门到精通之第十六节:U-boot分析
简介 u-boot最初是由PPCBoot发展而来的,可以引导多种操作系统、支持多种架构的CPU,它对PowerPC系列处理器的支持最为完善,而操作系统则对Linux系统的支持最好目前已成为Armboot和PPCboot的替代品。 特点: 主要支持操作系统:Linux、NetBSD、 VxWorks、QNX、RTEMS、ARTOS、L…...
UART 串口通信
第18.1讲 UART串口通信原理讲解_哔哩哔哩_bilibili 并行通信 一个周期同时发送8bit的数据,占用引脚资源多 串行通信 串行通信的通信方式: 同步通信 同一时钟下进行数据传输 异步通信 发送设备和接收设备的时钟不同 但是需要约束波特率(…...
【硬件】P沟道和N沟道MOS管开关电路设计
场效应管做的开关电路一般分为两种,一种是N沟道,另一种是P沟道,如果电路设计中要应用到高端驱动的话,可以采用PMOS来导通。P沟道MOS管开关电路PMOS的特性,Vgs小于一定的值就会导通,当Vgs<0,即Vs>Vg,管…...
中移杭研一面经历
文章目录 1、常用的Java元注解@Documented@Target@Retention@Override@Deprecated@Inherited@Repeatable@Native2、Java注解的原理3、spring boot starter开发过程1、原理浅谈2、大概步骤3、项目介绍1、常用的Java元注解 @Documented @Documented 是一个标记注解,没有成员变…...
阿里巴巴网站建设初衷/枫林seo工具
消息队列 场景模式基础架构发送原理异步发送同步发送分区生产者提高吞吐量:数据可靠性ack应答数据重复幂等性事务数据有序数据乱序broker工作流程follower故障leader故障数据查找文件清除高效读写消费者流程消费者组初始化分区分配策略自动提交offset手动提交指定位…...
做夺宝网站要办理什么/it培训班学出来有用吗
首先必须注意一般的.c文件和.h文件采用相同的函数名(如main.c和main.h定义) .c文件一般用于函数的实现,.h文件一般用于函数的声明 main.c内包含了所有用到的函数的头文件,实现函数的调用,从而完成函数的调用实现。 转载…...
网站排名突然消失/百度资源搜索
廉价磁盘冗余阵列(Redundant Array of Independent Disks) 作用:容错、提升读写速率 硬RAID: 需要RAID卡,有自己的CPU,处理速度快,有电池和无电池。 软RAID: 通过操作系统实现&am…...
兰州网站怎么建设/兰蔻搜索引擎营销案例
假如有一个包含产品目录的数据库表,其中每种类别的物品占一行。对于每种物品要存储的信息包含产品描述和价格,以及生产该产品的供应商信息。 现在,假如有由同一供应商生产的多种物品,那么在何处存储供应商信息(如供应…...
安徽蚌埠怀远县建设局网站/实体店怎么引流推广
好久没写东西了,前几天遇到一个企业,因为主域控在没有任何保护的情况下,裸奔后感染病毒,直接垮掉了(无语),且无法恢复。希望能够对其进行完整功能的灾难恢复,今天就跟大家分享一下恢…...
大学电子商务网站建设/网站快速被百度收录
在介绍实际的例子之前,然我们先了解下什么是mock? 为什么mock?mock的中文含义是假装模仿, 在单元测试里面我们测试的是某个单元的逻辑,即某个方法内的执行结果是否符合我们的预期。有一些方法会依赖于第三方的包&…...