当前位置:网站首页>线程间控制之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
边栏推荐
- 关于训练过程中损失函数出现断崖式增长的问题
- 使用itextpdf实现截取pdf文档第几页到第几页,进行分片
- Redis数据库讲解(一)
- Wechat applet obtains login user information, openid and access_ token
- Operation instructions of star boundary text automatic translator
- 帆软实现分页时第一行和最后两行冻结方式
- Nifi 快速安装及文件同步操作
- 云迁移的六大场景
- Chapter I review of e-commerce spike products
- pthread_ Why does self() repeat
猜你喜欢

室内外地图切换(室内基于ibeacons三点定位)

logback-logger和root

使用DialogFragment的一些感受及防踩坑经验(getActivity、getDialog为空,cancelable无效等)

Call wechat customer service applet

帆软之单元格部分字体变颜色

RecyclerView细节研究-RecyclerView点击错位问题的探讨与修复

关于云容灾,你需要知道这些

Operation instructions of star boundary text automatic translator

Wechat applet obtains login user information, openid and access_ token

Jmeter安装教程以及我遇到的问题的解决办法
随机推荐
leetcode--380. O (1) time insertion, deletion and acquisition of random elements
Research on recyclerview details - Discussion and repair of recyclerview click dislocation
pthread_ Why does self() repeat
教育行业云迁移最佳实践:海云捷迅使用HyperMotion云迁移产品为北京某大学实施渐进式迁移,成功率100%
openstack理论知识
mysql 5.1升级到5.68
Essential difference between restful WebService and gSOAP webservice
Understand the concepts of virtual base class, virtual function and pure virtual function (turn)
log4j 输出日志信息到文件中
FBS (fman build system) packaging
预览CSV文件
使用开源调研工具Prophet是一种什么体验?
01-NIO基础之ByteBuffer和FileChannel
Intégration de Clusters CDH Phoenix basée sur la gestion cm
星界边境文本自动翻译机使用说明
VMware installation 64 bit XP Chinese tutorial
Switch usage (wechat applet)
sql中出现一个变态问题
OpenStack如何跨版本升级
jacob打印word