当前位置:网站首页>线程间控制之CountDownLatch和CyclicBarrier使用介绍
线程间控制之CountDownLatch和CyclicBarrier使用介绍
2022-04-23 14:07:00 【pureluckyfish】
一、CountDownLatch介绍
CountDownLatch类(采用减法计数);是一个线程同步辅助工具类和CyclicBarrier类(采用加法计数)功能类似,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。
二、CountDownLatch俩种应用场景:
场景一:所有线程在等待开始信号startSignal.await(),主流程发出开始信号通知,既执行startSignal.countDown()方法后,所有线程才开始执行;每个线程执行完发出做完信号,既执行doneSignal.countDown()方法;当所有线程都执行完毕后,主流程才能继续往下执行。
package ThreadStudy;
import java.util.concurrent.CountDownLatch;
public class Driver1 {
public static void main(String[] args) throws InterruptedException {
int N = 5;
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(N);
for (int i = 0; i < N; i++) {
new Thread(new Work1(startSignal, doneSignal)).start();
}
//此时所有线程处于等待状态
System.out.println("doSomethingElse()");
//让所有线程执行
startSignal.countDown();
//等待所有线程执行完毕
doneSignal.await();
System.out.println("doSomethingElse()");
}
}
class Work1 implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
public Work1(CountDownLatch startSignal,CountDownLatch doneSignal) {
this.startSignal=startSignal;
this.doneSignal= doneSignal;
}
@Override
public void run() {
try {
startSignal.await();
doWork();
doneSignal.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void doWork() {
System.out.println("doWork()");
}
}
场景二:把一个大问题分成N个部分,每一个部分对应一个线程放到线程池中执行,当每一个线程执行完成完毕后发出做完信号,既调用doneSignal.countDown()方法;当所有线程都执行完毕后,主流程才能继续往下执行。
package ThreadStudy;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Driver2 {
public static void main(String[] args) throws Exception {
int N = 5;
CountDownLatch doneSignal = new CountDownLatch(N);
//定义线程池
ExecutorService exec = Executors.newSingleThreadExecutor();
for (int i = 0; i < N; i++) {
exec.execute(new Work2(doneSignal, i));
}
//等待所有线程执行完成
doneSignal.await();
System.out.println("doSomethingElse()");
//关闭线程池
exec.shutdown();
}
}
class Work2 implements Runnable {
private CountDownLatch doneSignal;
private int i;
public Work2(CountDownLatch doneSignal, int i) {
this.doneSignal = doneSignal;
this.i = i;
}
@Override
public void run() {
doWork(i);
doneSignal.countDown();
}
void doWork(int i) {
System.out.println("doWork():" + i);
}
}
三、CountDownLatch与CyclicBarrier对比
CountDownLatch | CyclicBarrier | |
相同点 | 都是同步辅助工具类 | |
不同点 | 减法计数,一次性使用 | 加法计数,可循环使用 |
构造方法 | CountDownLatch(int count) |
CyclicBarrier(int parties) |
CyclicBarrier(int parties, Runnable barrierAction) | ||
普通方法 | await() | await() |
await(long timeout, TimeUnit unit) | await(long timeout, TimeUnit unit) | |
countDown() | getNumberWaiting() | |
getCount() | getParties() | |
toString() | isBroken() | |
reset() |
四、CountDownLatch类中方法使用示例
package ThreadStudy;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class Csdn {
public static void main(String[] args) throws Exception {
int countLatch = 3;
// 创建指定个数的门闩
CountDownLatch countDownLatch = new CountDownLatch(countLatch);
System.out.println("toString方法0:" + countDownLatch.toString());
for (int i = 0; i < countLatch; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
// 门闩数减一
Thread.sleep(3000);
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
// 获取门闩数量
long n = countDownLatch.getCount();
System.out.println("门闩数量:" + n);
// 指定等待的超时时间
countDownLatch.await(1, TimeUnit.SECONDS);
System.out.println("过了超时时间程序继续往下执行");
// 当前线程等待,直到门闩数是0,程序才往下执行
countDownLatch.await();
System.out.println("toString方法1:" + countDownLatch.toString());
}
}
五、CyclicBarrier类中方法使用示例
package ThreadStudy;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
public class CyclicBarrierTest {
public static void main(String[] args) {
// 构造方法一:创建一个线程为3的循环障碍点,3个线程都到达障碍点后,才往下走!
CyclicBarrier cb1 = new CyclicBarrier(3);
// 构造方法二:创建一个新的CyclicBarrier,当最后一个线程通过障碍点后会触发此处的线程执行
CyclicBarrier cb = new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
System.out.println("==通过障碍点后触发执行的线程==");
}
});
// 返回当前在屏障处等待的人数。此方法主要用于调试和断言
int a = cb.getNumberWaiting();
System.out.println("返回当前在屏障处等待的人数" + a);
// 返回跨越该障碍所需的人数
int b = cb.getParties();
System.out.println("返回跨越该障碍所需的人数:" + b);
// 查询此屏障是否处于中断状态:
boolean bo = cb.isBroken();
System.out.println("查询此屏障是否处于中断状态:" + bo);
for (int i = 0; i < 4; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程:" + Thread.currentThread().getName() + "进入障碍点等待");
try {
// 等待,直到所有各方都调用了这个屏障上的await。
int d = cb.await();
System.out.println("d:" + d);
// 等待,直到所有各方都调用了此屏障上的await,或指定的等待时间过去
int c = cb.await(1, TimeUnit.SECONDS);
System.out.println("c:" + c);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("通过障碍点");
}
}).start();
}
// 复位操作,此时在障碍点等待的线程会抛出BrokenBarrierException异常
cb.reset();
}
}
版权声明
本文为[pureluckyfish]所创,转载请带上原文链接,感谢
https://blog.csdn.net/sinat_33918956/article/details/122469143
边栏推荐
- DDT+Excel进行接口测试
- How QT designer adds resource files
- Understand the concepts of virtual base class, virtual function and pure virtual function (turn)
- DeepinV20安装Mariadb
- 修改ddt生成的测试用例名称
- sql中出现一个变态问题
- Promtail + Loki + Grafana 日志监控系统搭建
- Wechat applet input hidden and inoperable settings
- VMWare安装64位XP中文教程
- 基于ibeacons签到系统
猜你喜欢
Easyexcel读取excel表地理位置数据,按中文拼音排序
什么是云迁移?云迁移的四种模式分别是?
帆软中需要设置合计值为0时,一整行都不显示的解决办法
POI operation word template replaces data and exports word
Wechat applet obtains login user information, openid and access_ token
Jmeter设置环境变量支持在任意终端目录输入jmeter直接启动
Windos中安装labellmg教程
Research on recyclerview details - Discussion and repair of recyclerview click dislocation
RecyclerView进阶使用-实现仿支付宝菜单编辑页面拖拽功能
正则表达式
随机推荐
服务器日志分析工具(识别,提取,合并,统计异常信息)
什么是云迁移?云迁移的四种模式分别是?
回顾2021:如何帮助客户扫清上云最后一公里的障碍?
Call wechat customer service applet
Can I compile the header file and source file of the template separately
室内外地图切换(室内基于ibeacons三点定位)
openstack理论知识
postman批量生产body信息(实现批量修改数据)
poi操作word模板替换数据并且导出word
使用DialogFragment的一些感受及防踩坑经验(getActivity、getDialog为空,cancelable无效等)
关于训练过程中损失函数出现断崖式增长的问题
mysql 5.1升级到5.68
某政务云项目业务系统迁移调研实践
在MAC上安装mysql
mysql 5.1升级到5.611
RecyclerView进阶使用-实现仿支付宝菜单编辑页面拖拽功能
PySide2
Visio installation error 1:1935 2: {XXXXXXXX
Prediction of tomorrow's trading limit of Low Frequency Quantization
Postman的安装使用及填坑心得