一句话说清楚 CountDownLatch 和 CyclicBarrier 的区别
时间:2022-07-25
本文章向大家介绍一句话说清楚 CountDownLatch 和 CyclicBarrier 的区别,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
日常工作中,经常会碰到这样的场景:有时候数据量特别大,任务量特别多,我们通常会开启多线程去分批执行任务,在所有任务执行完了之后,再去执行接下来的作业。
这时候,会想到 java 并发包提供的基础工具类,其中 有 CountDownLatch 和 CyclicBarrier ,它们都是提供多线程环境的协调功能,但是具体有什么区别呢?
CountDownLatch 操作的是事件,阻塞足够多的次数即可,不管几个线程;而 CyclicBarrier 侧重点是线程,强调多个线程间互相等待,同时结束。
01
CountDownLatch 用法
从代码层面,CountDownLatch 的用法是:
// 设置10个计数
CountDownLatch countDownLatch = new CountDownLatch(10);
// 每次调用即可减1
countDownLatch.countDown();
// 其他线程一直等待减到0后,才继续执行
countDownLatch.await()
从一个场景出发:
现在有订单库和派送单库,先查询订单,再查询派送单,之后对比订单和派送单,将差异写入差异库。
其中查询订单库和查询派送单库,可以用两个线程并行执行。都执行完了之后,才执行对账。
我们可以写一下伪代码:
Executor executor = Executors.newFixedThreadPool(2);
while(存在未对账订单) {
// 计数器初始化为2
CountDownLatch latch = new CountDownLatch(2);
// 查询未对账订单
executor.execute(() -> {
pOrders = getPOrders();
latch.countDown();
});
// 查询派送单
executor.execute(()-> {
dOrders = getDOrders();
latch.countDown();
});
// 等待两个查询结束
latch.await();
// 执行对账操作
diff = check(pOrders,dOrders);
// 差异写入差异库
save(diff);
}
我们使用只有2个核心线程的线程池,分别执行查询订单和派送单的操作,并且初始化了一个大小为 2 的 CountDownLatch,每次查询完后,都要 countDown();
主线程则一直等待减为 0 了之后,才开始继续往下执行。
02
CyclicBarrier 用法
从代码使用角度来说:
// 初始化值为5的栅栏
CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
// 每个线程调用 await()
cyclicBarrier.await();
// 等到有 5 个线程都执行了 await() 之后,继续执行。
// 并且 栅栏的 计数器会自动重置为 5 ,可以接着用
然后我们模拟一个场景
在英雄联盟中,选好英雄之后,会等待所有 10 个玩家进度条都到 100% 才开始游戏,我们可以使用 CyclicBarrier 来模拟这个场景
public class CyclicBarrierTest {
private final static ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(5);
private final static CyclicBarrier BARRIER = new CyclicBarrier(10);
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
final String name = "玩家" + i;
EXECUTOR_SERVICE.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println(name + "已准备,等待其他玩家准备...");
BARRIER.await();
Thread.sleep(1000);
System.out.println(name + "已加入游戏");
} catch (InterruptedException e) {
System.out.println(name + "离开游戏");
} catch (BrokenBarrierException e) {
System.out.println(name + "离开游戏");
}
}
});
}
EXECUTOR_SERVICE.shutdown();
}
}
最后,比较一下 CountDownLatch 和 CyclicBarrier 的不同点:
- CountDownLatch 是不可以重置的,所以无法重用;而 CyclicBarrier 则没有这个限制,可以重用;
- CountDownLatch 的基本操作组合是 countDown/await。调用 await 的线程阻塞等待 countDown 足够多的次数,不管你是在一个线程还是多个线程里 countDown,只要次数足够即可。
- CyclicBarrier 的基本操作组合,则就是 await,当所有伙伴 (parties)都调用了 await,才会继续进行任务,并自动进行重置。
- 注意,正常情况下,CyclicBarrier 的重置都是自动发生的,如果我们调用 reset 方法,但还有线程在等待,就会导致等待线程被打扰,抛出 BrokenBarrierException 异常。
- CyclicBarrier 侧重点是线程,而不是调用事件,它的典型应用场景是用来等待并发线程结束。
- android am 命令简单讲解(一)
- 渗透测试专用版Linux:BackBox3.13发布
- android dumpsys 快速入门
- 不容小觑的金融诈骗手段 – 419诈骗
- 新年伊始,微软再遭叙利亚电子军挑衅
- 任天堂3DS游戏机烧录卡蓝屏事件
- android调用dialog.hide()引起的输入事件派发错误问题追踪
- 互联网世界的毒瘤——僵尸网络
- android 游戏移植 (一) (文末有福利) | SDL 西游释厄传调试
- 自制分布式漏洞扫描工具
- [细节剖析]X Windows中一个22年的漏洞
- android 游戏移植 (二) | SDL2.0适配 西游释厄传
- Android调用系统相册和拍照的Demo
- 黑客是如何通过RDP远程桌面服务进行攻击的
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Flutter SingleChildScrollView 滚动控件
- Flutter Stack、Positioned 层叠布局
- Flutter Row、Column 线性布局
- 第21天:NLP实战(五)——词向量Skip-gram实践
- ES10(2019)有哪些更新和新特性?
- Flutter Icon IconFont(图标控件)
- Flutter TextField(输入控件)
- 常见的面试问题总结
- Flutter Button(按钮控件)
- 终极干货,数组去重且显示每一个数据重复的次数
- VUE引入 script, link
- Flutter Text(文本控件)
- 纯JS实现在一个字符串b中查找另一个字符串a出现的所有位置,并且不使用字符串的方法(递归)
- 【剑指Offer】替换空格
- 面试汇总(一):针对百度面试总结