文章目录

  • CyclicBarrier的方法
  • CyclicBarrier的使用

java中CyclicBarrier的使用

CyclicBarrier是java 5中引入的线程安全的组件。它有一个barrier的概念,主要用来等待所有的线程都执行完毕,然后再去执行特定的操作。

假如我们有很多个线程,每个线程都计算出了一些数据,然后我们需要等待所有的线程都执行完毕,再把各个线程计算出来的数据加起来,的到最终的结果,那么我们就可以使用CyclicBarrier。

CyclicBarrier的方法

我们先看下CyclicBarrier的构造函数:

    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);}

CyclicBarrier有两个构造函数,第一个只接受一个参数,表示需要统一行动的线程个数。第二个参数叫做barrierAction,表示出发barrier是需要执行的方法。

其中barrierAction是一个Runnable,我们可以在其中定义最后需要执行的工作。

再看下重要await方法:

    public int await() throws InterruptedException, BrokenBarrierException {try {return dowait(false, 0L);} catch (TimeoutException toe) {throw new Error(toe); // cannot happen}}public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException {return dowait(true, unit.toNanos(timeout));}

await也有两个方法,一个是带时间参数的,一个是不带时间参数的。

await本质上调用了lock.newCondition().await()方法。

因为有多个parties,下面我们考虑两种情况。

  1. 该线程不是最后一个调用await的线程

在这种情况下,该线程将会进入等待状态,直到下面的情况发送:

  • 最后一个线程调用await()
  • 其他线程中断了当前线程
  • 其他线程中断了其他正在等待的线程
  • 其他线程在等待barrier的时候超时
  • 其他线程在该barrier上调用的reset()方法

如果该线程在调用await()的时候已经设置了interrupted的状态,或者在等待的时候被interrupted,那么将会抛出InterruptedException异常,并清除中断状态。(这里和Thread的interrupt()方法保持一致)

如果任何线程正在等待状态中,这时候barrier被重置。或者在线程调用await方法或者正在等待中,barrier被broken,那么将会抛出BrokenBarrierException。

如果任何线程在等待的时候被中断,那么所有其他等待的线程将会抛出BrokenBarrierException,barrier将会被置为broken状态。

  1. 如果该线程是最后一个调用await方法的

在这种情况,如果barrierAction不为空,那么该线程将会在其他线程继续执行前调用这个barrierAction。

如果该操作抛出异常,那么barrier的状态将会被置为broken状态。

再看看这个reset() 方法:

    public void reset() {final ReentrantLock lock = this.lock;lock.lock();try {breakBarrier();   // break the current generationnextGeneration(); // start a new generation} finally {lock.unlock();}}

该方法将会将barrier置为broken状态,并且开启一个新的generation,来进行下一轮的操作。

CyclicBarrier的使用

我们在子线程中生成一个随机的整数队列,当所有的线程都生成完毕之后,我们再将生成的整数全都加起来。看下怎么实现。

定义生成整数队列的子线程:

public class CyclicBarrierUsage implements Runnable {private CyclicBarrier cyclicBarrier;private List<List<Integer>> partialResults;private Random random = new Random();public CyclicBarrierUsage(CyclicBarrier cyclicBarrier,List<List<Integer>> partialResults){this.cyclicBarrier=cyclicBarrier;this.partialResults=partialResults;}@Overridepublic void run() {String thisThreadName = Thread.currentThread().getName();List<Integer> partialResult = new ArrayList<>();// Crunch some numbers and store the partial resultfor (int i = 0; i < 10; i++) {Integer num = random.nextInt(10);System.out.println(thisThreadName+ ": Crunching some numbers! Final result - " + num);partialResult.add(num);}partialResults.add(partialResult);try {System.out.println(thisThreadName+ " waiting for others to reach barrier.");cyclicBarrier.await();} catch (InterruptedException e) {// ...} catch (BrokenBarrierException e) {// ...}}}

上面的子线程接收外部传入的cyclicBarrier和保存数据的partialResults,并在运行完毕调用cyclicBarrier.await()来等待其他线程执行完毕。

看下CyclicBarrier的构建:

CyclicBarrier cyclicBarrier=new CyclicBarrier(5,()->{String thisThreadName = Thread.currentThread().getName();System.out.println(thisThreadName + ": Computing sum of 5 workers, having 10 results each.");int sum = 0;for (List<Integer> threadResult : partialResults) {System.out.print("Adding ");for (Integer partialResult : threadResult) {System.out.print(partialResult+" ");sum += partialResult;}System.out.println();}System.out.println(thisThreadName + ": Final result = " + sum);});

在CyclicBarrier中,我们定义了一个BarrierAction来做最后数据的汇总处理。

运行:

        for (int i = 0; i < 5; i++) {Thread worker = new Thread(new CyclicBarrierUsage(cyclicBarrier,partialResults));worker.setName("Thread " + i);worker.start();}

输出结果如下:

Spawning 5 worker threads to compute 10 partial results each
Thread 0: Crunching some numbers! Final result - 5
Thread 0: Crunching some numbers! Final result - 3
Thread 1: Crunching some numbers! Final result - 1
Thread 0: Crunching some numbers! Final result - 7
Thread 1: Crunching some numbers! Final result - 8
Thread 0: Crunching some numbers! Final result - 4
Thread 0: Crunching some numbers! Final result - 6
Thread 0: Crunching some numbers! Final result - 9
Thread 1: Crunching some numbers! Final result - 3
Thread 2: Crunching some numbers! Final result - 1
Thread 0: Crunching some numbers! Final result - 0
Thread 2: Crunching some numbers! Final result - 9
Thread 1: Crunching some numbers! Final result - 3
Thread 2: Crunching some numbers! Final result - 7
Thread 0: Crunching some numbers! Final result - 2
Thread 2: Crunching some numbers! Final result - 6
Thread 1: Crunching some numbers! Final result - 6
Thread 2: Crunching some numbers! Final result - 5
Thread 0: Crunching some numbers! Final result - 0
Thread 2: Crunching some numbers! Final result - 1
Thread 1: Crunching some numbers! Final result - 5
Thread 2: Crunching some numbers! Final result - 1
Thread 0: Crunching some numbers! Final result - 7
Thread 2: Crunching some numbers! Final result - 8
Thread 1: Crunching some numbers! Final result - 2
Thread 2: Crunching some numbers! Final result - 4
Thread 0 waiting for others to reach barrier.
Thread 2: Crunching some numbers! Final result - 0
Thread 2 waiting for others to reach barrier.
Thread 1: Crunching some numbers! Final result - 7
Thread 1: Crunching some numbers! Final result - 6
Thread 1: Crunching some numbers! Final result - 9
Thread 1 waiting for others to reach barrier.
Thread 3: Crunching some numbers! Final result - 9
Thread 3: Crunching some numbers! Final result - 3
Thread 3: Crunching some numbers! Final result - 8
Thread 3: Crunching some numbers! Final result - 8
Thread 3: Crunching some numbers! Final result - 1
Thread 3: Crunching some numbers! Final result - 8
Thread 3: Crunching some numbers! Final result - 0
Thread 3: Crunching some numbers! Final result - 5
Thread 3: Crunching some numbers! Final result - 9
Thread 3: Crunching some numbers! Final result - 1
Thread 3 waiting for others to reach barrier.
Thread 4: Crunching some numbers! Final result - 2
Thread 4: Crunching some numbers! Final result - 2
Thread 4: Crunching some numbers! Final result - 5
Thread 4: Crunching some numbers! Final result - 5
Thread 4: Crunching some numbers! Final result - 3
Thread 4: Crunching some numbers! Final result - 7
Thread 4: Crunching some numbers! Final result - 4
Thread 4: Crunching some numbers! Final result - 8
Thread 4: Crunching some numbers! Final result - 4
Thread 4: Crunching some numbers! Final result - 3
Thread 4 waiting for others to reach barrier.
Thread 4: Computing sum of 5 workers, having 10 results each.
Adding 5 3 7 4 6 9 0 2 0 7
Adding 1 9 7 6 5 1 1 8 4 0
Adding 1 8 3 3 6 5 2 7 6 9
Adding 9 3 8 8 1 8 0 5 9 1
Adding 2 2 5 5 3 7 4 8 4 3
Thread 4: Final result = 230Process finished with exit code 0

本文的例子可以参考https://github.com/ddean2009/learn-java-concurrency/tree/master/CyclicBarrier

更多精彩内容且看:

  • 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
  • Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
  • Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
  • java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程

更多教程请参考 flydean的博客

java中CyclicBarrier的使用相关推荐

  1. exchanger_如何通过示例在Java中使用Exchanger

    exchanger 大家好,如果您在并发Java应用程序中工作,那么您可能听说过java.util.concurrent包的Exchanger类. Java中的Exchanger是Java 1.5中与 ...

  2. 如何通过示例使用Java中的Exchanger

    大家好,如果您在并发Java应用程序中工作,那么您可能听说过java.util.concurrent包的Exchanger类. Java中的Exchanger是Java 1.5中与CountDownL ...

  3. Java并发– CyclicBarrier示例

    Java中的CyclicBarrier是JDK 5中java.util.Concurrent包中引入的同步器,以及其他并发实用程序(如Counting Semaphore , BlockingQueu ...

  4. java 中如何正确的停止线程

    如何优雅的停止一个线程 1.为什么要停止线程 2.为何说要正确的停止线程 3.使用interrupt()停止线程 4.线程在通常三种情况下停止 4.1 普通情况 4.2 线程阻塞情况 4.3 传递中断 ...

  5. 12月18日云栖精选夜读 | Java 中创建对象的 5 种方式!...

    作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象.然而这里有很多创建对象的方法,我们会在这篇文章中学到. Java中有5种创建对象的方式,下面给出它们的 ...

  6. Java 中如何模拟真正的同时并发请求?

    有时需要测试一下某个功能的并发性能,又不要想借助于其他工具,索性就自己的开发语言,来一个并发请求就最方便了. java中模拟并发请求,自然是很方便的,只要多开几个线程,发起请求就好了.但是,这种请求, ...

  7. Thinking in Java 中闪耀的星星(四)

    51.对象序列化的具体应用 这也是书里的一个例子,挺有意思的.结合模板方法模式模拟CAD将用户作业的信息保存在文件中: import java.io.*; import java.util.*; ab ...

  8. 《Java并发编程的艺术》——Java中的并发工具类、线程池、Execute框架(笔记)

    文章目录 八.Java中的并发工具类 8.1 等待多线程完成的CountDownLatch 8.2 同步屏障CyclicBarrier 8.2.1 CyclicBarrier简介 8.2.2 Cycl ...

  9. 《Java并发编程的艺术》读后笔记-Java中的并发工具类(第八章)

    文章目录 <Java并发编程的艺术>读后笔记-Java中的并发工具类(第八章) 1.等待多线程完成的CountDownLatch 2.同步屏障CyclicBarrier 2.1 Cycli ...

最新文章

  1. 怎么进u8系统服务器网址,服务器地址变更后如何进入u8
  2. 最长回文子串--马拉车(?)
  3. linux虚拟用户的配置
  4. msf 启动报[-] * WARNING: No database support: No database YAML file解决方法
  5. 自己写的thinkphp自动生成类
  6. 04需求工程软件建模与分析阅读笔记之四
  7. 互联网下半场的角逐,玩转轻资产的大数据服务 | 阿里云栖开发者沙龙大数据专场(北京站)干货集锦...
  8. 如果没有就插入,如果有就更新
  9. [转]使用npm发布vue组件
  10. 腾讯“立知”被指抄袭“即刻” APP,目前已被下线
  11. (转)[Cocoa]深入浅出 Cocoa 之 Framework
  12. EIGRP的扩展实验
  13. 什么是servlet技术?如何部署和新建一个servlet?
  14. WIN7 X64完美卸载SQL2008 R2并重装SQL2008
  15. java笔试题大全带答案_java笔试题大全带答案(经典11题)
  16. 幂级数——函数的幂级数展开
  17. Himawari-8数据下载及命名
  18. ADT下载地址,完整版
  19. 西门子s7-200解密软件下载_西门子S7200plc软件仿真软件使用方法
  20. 介绍一些ddos产品的厂家

热门文章

  1. 安卓入门系列-05常见布局之RelaiveLayout(相对布局)
  2. 0x5f3759df的数学原理
  3. POJ1151(线段树+扫描线求矩形面积并)
  4. EXE和SYS通信(ReadFile WriteFile DO_DIRECT_IO) 直接方式
  5. 漫游Kafka实战篇之搭建Kafka运行环境
  6. 【Boost】boost库中thread多线程详解12——线程的分离与非分离
  7. 长连接和Keepalive
  8. MFC下CSocket编程详解
  9. Wireshark网卡抓包工具简明教程
  10. scrapy框架的概念和流程