当前位置:网站首页>线程间控制之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
边栏推荐
- CDH cluster integration Phoenix based on CM management
- mysql 5.1升级到5.69
- pthread_ Why does self() repeat
- RecyclerView高级使用(一)-侧滑删除的简单实现
- 更改plsql工具栏的图标大小
- 帆软调用动态传参的方法,在标题中设置参数
- 政务云迁移实践 北明数科使用HyperMotion云迁移产品为某政府单位实施上云迁移项目,15天内完成近百套主机迁移
- 微信小程序的订阅号开发(消息推送)
- 报表FCRA考试题集及答案(错了11题)
- leetcode--357. Count the number of different figures
猜你喜欢
随机推荐
云迁移的六大场景
帆软中使用if else 进行判断-使用标题条件进行判断
Jacob print word
JSP学习2
HyperMotion云迁移完成阿里云专有云产品生态集成认证
leetcode--977. Squares of a Sorted Array
封装logging模块
On the multi-level certificate based on OpenSSL, the issuance and management of multi-level Ca, and two-way authentication
基于CM管理的CDH集群集成Phoenix
关于密匙传递的安全性和数字签名
连接公司跳板机取别名
VMWare安装64位XP中文教程
postman批量生产body信息(实现批量修改数据)
数据库DbVisualizer Pro报文件错误,导致数据连接失败
帆软中根据分类进行汇总
Can global variables be defined in header files
基于CM管理的CDH6.3.2集群集成Atlas2.1.0
RobotFramework 之 文件上传和下载
微信小程序获取登录用户信息、openid和access_token
Request module