CyclicBarrier

用来控制多个线程互相等待,只有当多个线程都到达时,这些线程才会继续执行。

和 CountdownLatch 相似,都是通过维护计数器来实现的。线程执行 await() 方法之后计数器会减 1,并进行等待,直到计数器为 0,所有调用 await() 方法而在等待的线程才能继续执行。

CyclicBarrier 和 CountdownLatch 的一个区别是,CyclicBarrier 的计数器通过调用 reset() 方法可以循环使用,所以它才叫做循环屏障。

CyclicBarrier 有两个构造函数,其中 parties 指示计数器的初始值,barrierAction 在所有线程都到达屏障的时候会执行一次。

public CyclicBarrier(int parties, Runnable barrierAction) {if (parties <= 0) throw new IllegalArgumentException();this.parties = parties;this.count = parties;this.barrierCommand = barrierAction;
}public CyclicBarrier(int parties) {this(parties, null);
}

demo示例

package com.leo.demo.juctest;import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @ClassName: CyclicBarrierExample* @Description: 关于CyclicBarrier的测试* @Author: leo825* @Date: 2020-04-28 23:48* @Version: 1.0*/
public class CyclicBarrierExample {public static void main(String[] args) {final int totalThread = 10;CyclicBarrier cyclicBarrier = new CyclicBarrier(totalThread);ExecutorService executorService = Executors.newCachedThreadPool();for (int i = 0; i < totalThread; i++) {executorService.execute(() -> {String threadName = Thread.currentThread().getName();System.out.println(threadName + " 开始准备...");try {cyclicBarrier.await();} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}System.out.println(threadName + " 准备结束...");});}executorService.shutdown();}
}

执行结果

pool-1-thread-1 开始准备...
pool-1-thread-2 开始准备...
pool-1-thread-3 开始准备...
pool-1-thread-4 开始准备...
pool-1-thread-5 开始准备...
pool-1-thread-6 开始准备...
pool-1-thread-7 开始准备...
pool-1-thread-8 开始准备...
pool-1-thread-9 开始准备...
pool-1-thread-10 开始准备...
pool-1-thread-10 准备结束...
pool-1-thread-1 准备结束...
pool-1-thread-2 准备结束...
pool-1-thread-3 准备结束...
pool-1-thread-4 准备结束...
pool-1-thread-5 准备结束...
pool-1-thread-6 准备结束...
pool-1-thread-7 准备结束...
pool-1-thread-9 准备结束...
pool-1-thread-8 准备结束...

CyclicBarrier 和 CountdownLatch

CyclicBarrier 和 CountdownLatch结合使用

有一个场景:男子100米短跑,需要知道每一个运动员成绩,并且打印第一名和最后一名。
具体实现如下:

package com.leo.demo.threadtest.countdownlatch;import java.math.BigDecimal;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;/*** @ClassName: Runner* @Description: 设计百米赛跑统计时间的小程序* 1、10个选手听信号枪,统一开始跑步* 2、打印出来每个选手耗时时间单位秒* 3、打印比赛总共耗时时间单位秒* @Author: leo825* @Date: 2019-08-21 09:28* @Version: 1.0*/
public class RunnerTest {public static void main(String[] args) throws InterruptedException, BrokenBarrierException {//设置10名跑步选手int runners = 10;//设置10+1个屏障,因为裁判也需要阻塞,裁判要先到终点CyclicBarrier cyclicBarrier = new CyclicBarrier(runners + 1);//设置主线程准备时间CountDownLatch countDownLatch = new CountDownLatch(1);//比赛准备时间long beginTime = System.currentTimeMillis();System.out.println("男子100米运动员就绪准备比赛");//使用随机数产生随机运行时间ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();//使用原子变量,模拟第一名成绩final AtomicInteger firstRunner = new AtomicInteger(0);//使用原子变量,模拟最后一名成绩final AtomicInteger lastRunner = new AtomicInteger(0);//模拟赛道上的运动员ExecutorService executor = Executors.newFixedThreadPool(runners);//运动员进入各自的跑道for (int i = 0; i < runners; i++) {//模拟百米赛跑运动员耗时int costTime = threadLocalRandom.nextInt(9690, 14000);//模拟运动员再各自跑道准备跑步executor.submit(() -> {try {String threadName = Thread.currentThread().getName();System.out.println(threadName + "运动员就绪!!!");try {//等待主线程完成的信号countDownLatch.await();if (firstRunner.get() == 0 || lastRunner.get() == 0) {firstRunner.set(costTime);lastRunner.set(costTime);} else {if (firstRunner.get() > costTime) {firstRunner.set(costTime);}if (lastRunner.get() < costTime) {lastRunner.set(costTime);}}TimeUnit.MICROSECONDS.sleep(costTime);System.out.println("运动员" + threadName + " 男子100米成绩为:" + transtCostTime(costTime) + "s");cyclicBarrier.await();} catch (Exception e) {e.printStackTrace();}} catch (Exception e) {e.printStackTrace();}});}//主线程准备时间long endTime = System.currentTimeMillis();System.out.println(Thread.currentThread().getName() + "准备时间:" + (endTime - beginTime) + "ms");//裁判发号施令开始比赛System.out.println("开始比赛...");countDownLatch.countDown();//裁判事先到终点等待,当数字到达10+1的时候开始释放锁cyclicBarrier.await();System.out.println("百米赛跑第一名成绩:" + transtCostTime(firstRunner.get()) + "s");System.out.println("百米赛跑最后一名成绩:" + transtCostTime(lastRunner.get()) + "s");executor.shutdown();}/*** 将毫秒转换成秒** @param costTime* @return*/private static BigDecimal transtCostTime(int costTime) {BigDecimal bigDecimal = new BigDecimal(costTime);bigDecimal = bigDecimal.divide(new BigDecimal(1000), 3, BigDecimal.ROUND_DOWN);return bigDecimal;}
}

打印结果如下:

男子100米运动员就绪准备比赛
main准备时间:180ms
开始比赛...
pool-1-thread-1运动员就绪!!!
pool-1-thread-2运动员就绪!!!
pool-1-thread-3运动员就绪!!!
pool-1-thread-6运动员就绪!!!
pool-1-thread-5运动员就绪!!!
pool-1-thread-4运动员就绪!!!
pool-1-thread-7运动员就绪!!!
pool-1-thread-8运动员就绪!!!
pool-1-thread-9运动员就绪!!!
pool-1-thread-10运动员就绪!!!
运动员pool-1-thread-4 男子100米成绩为:9.690s
运动员pool-1-thread-5 男子100米成绩为:10.209s
运动员pool-1-thread-2 男子100米成绩为:13.326s
运动员pool-1-thread-7 男子100米成绩为:9.692s
运动员pool-1-thread-10 男子100米成绩为:10.126s
运动员pool-1-thread-3 男子100米成绩为:10.350s
运动员pool-1-thread-8 男子100米成绩为:10.623s
运动员pool-1-thread-1 男子100米成绩为:11.263s
运动员pool-1-thread-6 男子100米成绩为:11.872s
运动员pool-1-thread-9 男子100米成绩为:11.433s
百米赛跑第一名成绩:9.690s
百米赛跑最后一名成绩:13.326s

J.U.C系列(二)CyclicBarrier的使用相关推荐

  1. 【C++自我精讲】基础系列二 const

    [C++自我精讲]基础系列二 const 0 前言 分三部分:const用法.const和#define比较.const作用. 1 const用法 const常量:const可以用来定义常量,不可改变 ...

  2. 机器学习入门系列二(关键词:多变量(非)线性回归,批处理,特征缩放,正规方程

    机器学习入门系列二(关键词:多变量(非)线性回归,批处理,特征缩放,正规方程) 目录(?)[+] 一多变量的线性回归 二批处理 三特征缩放 四正规方程 五多变量非线性回归 一.多变量的线性回归 在#机 ...

  3. 数学之美 系列二 -- 谈谈中文分词

    数学之美 系列二 -- 谈谈中文分词 2006年4月10日 上午 08:10:00 发表者: 吴军, Google 研究员 谈谈中文分词 ----- 统计语言模型在中文处理中的一个应用 上回我们谈到利 ...

  4. 微服务架构系列二:密码强度评测的实现与实验

    本文是继<微服务架构系列一:关键技术与原理研究>的后续,系列一中论述了微服务研究的背景和意义,主要调研了传统架构的发展以及存在的问题和微服务架构的由来,然后针对微服务架构的设计原则.容器技 ...

  5. 阵列信号DOA估计系列(二).导向矢量与空间FFT(附代码)

    阵列信号DOA估计系列(二).导向矢量 在DOA估计里面,经常会看到导向矢量这个名词,也有的地方叫方向矢量,方向矩阵,基本上都是array steering vector 的翻译. 本文首先对均匀线阵 ...

  6. 图机器学习(GML)图神经网络(GNN)原理和代码实现(前置学习系列二)

    图机器学习(GML)&图神经网络(GNN)原理和代码实现(PGL)[前置学习系列二] 上一个项目对图相关基础知识进行了详细讲述,下面进图GML networkx :NetworkX 是一个 P ...

  7. Linux快速入手系列二( 文本处理 )

    更多精彩文章点击 -> 我的学习小站 & 更多好玩点击 -> 技术杂谈 文本编辑神器-Vim vim的三种操作模式 vim有三种操作模式,分别是命令模式(Command mode) ...

  8. Linux学习系列二:Linux中的常用命令

    这个系列的Linux教程主要参考刘遄老师的<Linux就该这么学>.用的系统是RHEL8,如果遇见一些命令出现问题,请首先检查自己的系统是否一致,如果不一致,可网上查一下系统间某些命令之间 ...

  9. 算法系列(二):贪心算法--Huffman编码

    算法系列(二):贪心算法--Huffman编码 一.分析 问题描述: 哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法.其压缩率通常在20%-90%之间.哈夫曼编码算法使用字符在文件中出现的频率 ...

  10. A.图机器学习(GML)图神经网络(GNN)原理和代码实现(前置学习系列二)

    图学习图神经网络算法专栏简介:主要实现图游走模型(DeepWalk.node2vec):图神经网络算法(GCN.GAT.GraphSage),部分进阶 GNN 模型(UniMP标签传播.ERNIESa ...

最新文章

  1. C++vector迭代器失效的问题
  2. xpath提取html属性,xpath提取 html标签的文字内容
  3. tensorflow 动态数组 TensorArray
  4. 2014\Province_C_C++_B\3 李白打酒
  5. java oauth server_Spring OAuth2 ResourceServer外部AuthorizationServer
  6. Python | Lambda和map()与示例
  7. 荣耀30S首销全平台夺冠 赵明:满足消费者对5G的所有需求和想象
  8. Oracle 10G安装指导
  9. 淘宝打单发货API,淘宝打单发货接口
  10. NFT抢购合集工具(免费)
  11. 即时通信多媒体分享与文件共享
  12. 0210leetcode刷题5道python
  13. python打印心形改成中文之后变形了,Python打印心形图案
  14. 再见 Wordpress!这个开源建站神器有点吊
  15. 水漆哪个品牌好?十大品牌水漆排行榜
  16. parsec使用教程
  17. Swagger使用教程
  18. 精确查找top k和非精确查找top k
  19. 趣图:万一跑路失败被抓,可以这样解释
  20. Linux 内核观测技术 eBPF 中文入门指南

热门文章

  1. ABAP 使用DYNP_VALUES_READ来获取屏幕字段值
  2. 在vs2005中使用Com连接SAP系统(二)
  3. 自动关闭模态框_Dialog 弹出框
  4. 混凝土静力受压弹性模量试验计算公式_2019年度水运材料考试大纲微试验
  5. magento2 所需要php 扩展,Magento2如何通过Composer安装插件扩展
  6. linux如何get请求urlencode,如何为curl命令urlencode数据?
  7. php pcntl扩展下载,linux下如何安装PHP pcntl 扩展
  8. 饿了么外卖商家版电脑版_为什么有些美团、饿了么外卖商家生意那么好,单子也不少,但是却倒闭了?...
  9. lol服务器不稳定补偿地址,LOL9月4日更新bug补偿地址在哪里 9月4日更新bug补偿地址分享...
  10. php节点对象,JavaScript_JavaScript中访问节点对象的方法有哪些如何使用,JavaScript中访问节点对象的方法 - phpStudy...