CyclicBarrier
类介绍
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.

CyclicBarrier是一个同步工具类,它允许一组线程在到达某个栅栏点(common barrier point)互相等待,发生阻塞,直到最后一个线程到达栅栏点,栅栏才会打开,处于阻塞状态的线程恢复继续执行.它非常适用于一组线程之间必需经常互相等待的情况。CyclicBarrier字面理解是循环的栅栏,之所以称之为循环的是因为在等待线程释放后,该栅栏还可以复用。

示例一:简单模拟一下对战平台中玩家需要完全准备好了,才能进入游戏的场景。

public class BarrierDemo {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(5);
final CyclicBarrier barrier = new CyclicBarrier(5);
for (int i = 0; i < 5; i++) {
service.execute(new Player("玩家" + i, barrier));
}
service.shutdown();
}
}

public class Player implements Runnable {
private final String name;
private final CyclicBarrier barrier;

public Player(String name, CyclicBarrier barrier) {
this.name = name;
this.barrier = barrier;
}

public void run() {
try {
TimeUnit.SECONDS.sleep(1 + (new Random().nextInt(3)));
System.out.println(name + "已准备,等待其他玩家准备...");
barrier.await();
TimeUnit.SECONDS.sleep(1 + (new Random().nextInt(3)));
System.out.println(name + "已加入游戏");
} catch (InterruptedException e) {
System.out.println(name + "离开游戏");
} catch (BrokenBarrierException e) {
System.out.println(name + "离开游戏");
}

}
}
输出结果:

玩家0已准备,等待其他玩家准备...
玩家2已准备,等待其他玩家准备...
玩家1已准备,等待其他玩家准备...
玩家4已准备,等待其他玩家准备...
玩家3已准备,等待其他玩家准备...
玩家4已加入游戏
玩家1已加入游戏
玩家0已加入游戏
玩家3已加入游戏
玩家2已加入游戏

构造函数
CyclicBarrier有两个构造函数:

public CyclicBarrier(int parties)
public CyclicBarrier(int parties, Runnable barrierAction)

参数parties指定线程数量,当指定的线程值都到达栅栏点时,栅栏打开,线程恢复。需要注意的是,当指定的线程数量大于启动的线程数量,比如修改上例中的代码,只启动9个线程,那么所有的线程将一直处于等待状态。第二种情况是指定的线程数量小于启动的线程,上例代码,启动11个线程,那么当第十个线程到达栅栏点时,那么这十个线程就会恢复继续执行,而第十一个线程将一直处于阻塞状态。请大家自行修改代码验证。
CyclicBarrier还提供一个更高级的构造函数CyclicBarrier(int parties, Runnable barrierAction),用于在线程到达屏障时,优先执行barrierAction,方便处理更复杂的业务场景。代码如下:
示例二

public class BarrierDemo2 {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(5);
final CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {
public void run() {
System.out.println("所有线程已到达栅栏点");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
for (int i = 0; i < 5; i++) {
service.execute(new Player("玩家" + i, barrier));
}
service.shutdown();
}
}

输出结果为:

玩家4已准备,等待其他玩家准备...
玩家2已准备,等待其他玩家准备...
玩家1已准备,等待其他玩家准备...
玩家0已准备,等待其他玩家准备...
玩家3已准备,等待其他玩家准备...
所有线程已到达栅栏点
玩家0已加入游戏
玩家1已加入游戏
玩家3已加入游戏
玩家4已加入游戏
玩家2已加入游戏

常用方法介绍
await()
Waits until all parties have invoked await on this barrier.

调用该方法会使当前线程在栅栏点发生阻塞,直到指定的线程数量都达到栅栏点时恢复执行

await(long timeout, TimeUnit unit)
Waits until all parties have invoked await on this barrier, or the specified waiting time elapses.

类似于await(),增加了超时时间参数。
参考如下代码:

public void run() {
try {
TimeUnit.SECONDS.sleep(1 + (new Random().nextInt(3)));
System.out.println(name + "已准备,等待其他玩家准备...");
barrier.await(200, TimeUnit.MILLISECONDS);
TimeUnit.SECONDS.sleep(1 + (new Random().nextInt(3)));
System.out.println(name + "已加入游戏");
} catch (InterruptedException e) {
System.out.println(name + "离开游戏");
} catch (BrokenBarrierException e) {
System.out.println(name + "离开游戏");
} catch (TimeoutException e) {
System.out.println(name + "连接超时");
}
}

输出结果:

玩家3已准备,等待其他玩家准备...
玩家3连接超时
玩家0已准备,等待其他玩家准备...
玩家1已准备,等待其他玩家准备...
玩家0离开游戏
玩家1离开游戏
玩家4已准备,等待其他玩家准备...
玩家2已准备,等待其他玩家准备...
玩家4离开游戏
玩家2离开游戏

上面的代码修改了Player.java里面的run()方法,当barrier在等待点出等待超时时,会抛出TimeoutException异常,同时,位于该barrier上的其他线程也将毁抛出BrokenBarrierException异常。这里说明,barrier上的线程要么同时成功要么同时失败,不存在部分成功部分失败的场景。

getNumberWaiting()
Returns the number of parties currently waiting at the barrier.

返回当前在栅栏处等待的参与者数目。此方法主要用于调试和断言。

getParties()
Returns the number of parties required to trip this barrier.

该方法可以获得构造函数中指定的需要在栅栏点阻塞的线程数量

isBroken()
Queries if this barrier is in a broken state

查询此栅栏是否处于损坏状态。

reset()
Resets the barrier to its initial state.

将barrier重置为其初始状态。如果所有参与者目前都在屏障处等待,则它们将返回,同时抛出一个 BrokenBarrierException
---------------------
作者:小鱼儿Eason
来源:CSDN
原文:https://blog.csdn.net/yin380697242/article/details/53313622
版权声明:本文为博主原创文章,转载请附上博文链接!

java多线程 栅栏CyclicBarrier的更多相关文章

  1. 多线程-栅栏CyclicBarrier

    上一篇总结了闭锁CountDownLatch,这一篇总结一下栅栏CyclicBarrier.它们两者之间的区别主要是,闭锁是等待一个事件发生,比如上一篇的田径比赛,运动员等待裁判哨声一响就可以开始跑, ...

  2. java 多线程 day15 CyclicBarrier 路障

    import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.ut ...

  3. java 多线程 一个博客

    http://blog.csdn.net/a352193394/article/category/2563875 Java多线程之~~~线程安全容器的非阻塞容器 在并发编程中,会经常遇到使用容器.但是 ...

  4. java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)

    -闭锁(Latch) 闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态.通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻断,一旦大门打开所有线程都将通过, ...

  5. Java并发编程原理与实战二十七:循环栅栏:CyclicBarrier

    昨天我们学习了倒计数功能的等待,今天我们学习的是循环栅栏:CyclicBarrier.下面我们就开始吧: 1.CyclicBarrier简介CyclicBarrier,是JDK1.5的java.uti ...

  6. java高并发系列 - 第17天:JUC中的循环栅栏CyclicBarrier常见的6种使用场景及代码示例

    这是java高并发系列第17篇. 本文主要内容: 介绍CyclicBarrier 6个示例介绍CyclicBarrier的使用 对比CyclicBarrier和CountDownLatch Cycli ...

  7. Java多线程工具类之循环栅栏计数器

    Java多线程下循环计数器 本文主要内容:CyclicBarrier(下文中凯哥就用cycBar来代替)定义介绍:举例说明:代码演示:从源码来看原理及总结:CyclicBarrier与CountDow ...

  8. java多线程10:并发工具类CountDownLatch、CyclicBarrier和Semaphore

    在JDK的并发包(java.util.concurrent下)中给开发者提供了几个非常有用的并发工具类,让用户不需要再去关心如何在并发场景下写出同时兼顾线程安全性与高效率的代码. 本文分别介绍Coun ...

  9. java多线程--同步屏障CyclicBarrier的使用

    CyclicBarrier的概念理解: CyclicBarrier的字面上的意思是可循环的屏障,是java并发包java.util.concurrent 里的一个同步工具类,在我下载的JDK1.6的中 ...

随机推荐

  1. virtualbox复制虚拟机网络问题

    virtulbox复制虚拟机由于mac地址问题会导致网卡不可以用 1:修改mac地址 需要在virtualbox修改虚拟机网络选项卡下面的mac地址 2:修改ifcfg-eth0 把HWADDR的值设 ...

  2. execve(".. ",[".. ",".. "],[/* ..*/])第二个 参数 数组硬传

    strace.第一次跟踪点东西的启动. 第一次看见..execve(".. ",[".. ",".. "],[/* ..*/]) 第二个 参 ...

  3. MVC之htmlhelper总结

    自学习mvc以来,htmlhelper使用的也非常多,下面开始总结一下吧,由于本人比较懒,内容大部分摘自slark.net的笔记, 有人问为什么用这个htmlhelper,我就喜欢用原生的标签,这个按 ...

  4. IOC与依赖注入

    spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入什么?控 ...

  5. 市场上主流的BI产品的“答案之书”

    本文来自网易云社区. 从20世纪80年代开始,商业智能的定义出现在人们面前,早期商业智能十分基础和杂乱,不仅仅会把数据处理放进去.还包含有一些可视化方面内容等.这个时期的BI主要的功能是支持多维分析和 ...

  6. c++滚动数组

    说来惭愧,我老早以前就学习了dp,可直到最近才知道滚动数组. 所以说,滚动数组是什么呢? 它是一种优化dp空间复杂度的思想. 在dp转移时,我们往往不需要之前推的所有的,而是只需要前一两个转移的. 我 ...

  7. 十天入门java教程 Day01

    这几年一直在想学一门语言,java,Python,php也都看过,但是没有一门是精的.语言学习并不是写出hello world就行了.个人感觉需要静心去学习. java语言是什么? java是一种计算 ...

  8. No module named 'numpy.core._multiarray_umath'

    问题:基于anaconda prompt 安装好TensorFlow框架以后,引入的时候(import tensorflow as tf)报如下图片的错误: 回答:网上好多人说是需要升级numpy,我 ...

  9. async/await 处理异步

    async/ await来发送异步请求,从服务端获取数据,代码很简洁,同时async/await 已经被标准化. 先说一下async的用法,它作为一个关键字放到函数前面,用于表示函数是一个异步函数,因 ...

  10. SQL事务对并发处理的支持

    前言 继上次技术分享后,学到了关于mysql事务的许多新知识,感觉还是蛮有收获的.后来反过来想想,这些东西其实我们都接触过,最起码在自学考试的数据库系统原理那本书里面对事务的讲解,在里面就提到了事务的 ...