并发编程系列之CountDownLatch用法简介
2023-03-20 14:55:19 时间
1、 CountDownLatch倒计数锁存器
CountDownLatch:用于协同控制一个或多个线程等待在其他线程中执行的一组操作完成,然后再继续执行
2、 CountDownLatch用法
- 构造方法:CountDownLatch(int count),count指定等待的条件数(任务数、操作数),不可再更改
- 等待方法:await(),阻塞等待线程直到count减少为0,count为0时,不会阻塞,继续执行
- boolean await(long timeout,TimeUnit unit):可以设置超时时间的await方法,返回true表示等待条件到达;false表示条件未来到达,但超时了
- long getCount():获取当前计数值,常用于调试或者测试
CountDownLatch注意事项:只可使用一次,不能重复使用,计数变为0之后,就不可再用
3、CountDownLatch适用场景
- 等待多个条件完成,
countDownLatch(N)
这个多个条件可以是:等待N个线程、等待N个操作、等待某操作的N次执行 - 用于并发测试,等待多个线程一起出发
4、CountDownLatch例子
例子:等待n个线程执行完成,再一起执行
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) {
final CountDownLatch cdl = new CountDownLatch(1);
int concurrency = 100;
final Random random = new Random();
for (int i = 0; i < concurrency; i++) {
new Thread(()->{
try {
Thread.sleep(random.nextInt(10_000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "准备就绪");
// 让并发线程都等待发出信号
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "开始工作");
}).start();
}
System.out.println("******************** 发出开始信号***********");
cdl.countDown();
}
}
执行,发现结果不符合我们的要求,虽然也是多个线程等待,再一起无序执行:
******************** 发出开始信号***********
Thread-22准备就绪
Thread-22开始工作
Thread-45准备就绪
Thread-45开始工作
...
因为CountDownLatch不能重用,所以再新加一个CountDownLatch协同N个线程:
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class StartTogerCountdownLatchExample {
public static void main(String[] args) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(1);
int concurrency = 100;
final CountDownLatch cdln = new CountDownLatch(concurrency);
final Random random = new Random();
for (int i = 0;i < concurrency; i++) {
new Thread(()->{
try {
Thread.sleep(random.nextInt(10_000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(
Thread.currentThread().getName() + " 准备就绪");
// 调用countDown()报告完成任务
cdln.countDown();
// 让所有线程都等待发出信号
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(
Thread.currentThread().getName() + " 开始工作");
}).start();
}
//等待准备完成
cdln.await();
System.out.println("******************** 发出开始信号***********");
cdl.countDown();
}
}
等待N个线程准备就绪,然后一个总的CountDownLatch发出信号量,所有线程一起执行
...
Thread-11 准备就绪
Thread-14 准备就绪
Thread-53 准备就绪
Thread-91 准备就绪
******************** 发出开始信号***********
Thread-97 开始工作
Thread-57 开始工作
...
相关文章
- 深入探讨Java中的异常与错误处理
- 研究学习Kotlin的一些方法
- 数据显示Java热度持续下落,日子屈指可数?
- 2017年5月编程语言排行榜:Java与C语言优势正开始缩小
- Java多线程之内置锁与显示锁
- Java线程池的理论与实践
- 白话阿里巴巴Java开发手册(编程规约)
- 关于Java你不知道的十件事
- Java服务化系统线上应急和技术攻关,你必须掌握的Linux命令
- Java实现高斯模糊和图像的空间卷积
- Java阻塞队列实现原理分析
- NPM使用技巧
- Node.js对Java开发者而言是什么?
- Java反射机制应用实践
- 理解RxJava中的Single和Completable
- 2017年你不能错过的Java类库
- 大规模集群下的Hadoop NameNode
- 从源码解密Spark内存管理
- 2017年3月编程语言排行榜:Swift首次进入前十
- JVM热点技术:Java类的加载机制