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. ubuntu apt指令分析

    ubunut安装软件时候需要查看源内可供选择的安装包的一些信息,此处提供一些指令方便以后查阅 apt-get sudo apt-get update #更新源 sudo apt-get upgrade ...

  2. alias这个命令还是很有用的

    这是在知乎看到的一个回答. 我一开始学习linux命令的时候觉得这个alias命令很奇怪,为什么要给别人起个别名呢?有什么好处? 因为当时接触的是比较简单的命令 比如ls -al的这种短小的命令,对a ...

  3. [学习笔记]父进程wait和waitpid

    1.wait和waitpid出现的原因 SIGCHLD q  当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止) q  子进程退 ...

  4. 关于eclipse导入maven项目

    1:删除其他的配置文件,只需要源码 和 pom文件 2:导入项目,再修改几个地方: 2.1: 所选项目右键- properties - Project Facet,勾上 Dynamic Web Mod ...

  5. 值得细读!如何系统有效地提升Android代码的安全性?

    众所周知,代码安全是Android开发工作中的一大核心要素. 11月3日,安卓巴士全球开发者论坛线下系列沙龙第七站在成都顺利举办.作为中国领先的安卓开发者社区,安卓巴士近年来一直致力于在全国各大城市举 ...

  6. selenium自动化测试、Python单元测试unittest框架以及测试报告和日志输出

    部分内容来自:https://www.cnblogs.com/klb561/p/8858122.html 一.基础介绍 核心概念:test case, testsuite, TestLoder,Tex ...

  7. 【转】php通过curl跨域向asp.net服务器上传文件及参数

    转:http://blog.sina.com.cn/s/blog_13331dce50102vq32.html 这是一个由php通过调用asp.net接口向asp.net服务器post上传文件及参数并 ...

  8. IMP-00003: 遇到 ORACLE 错误 959 ORA-00959: 表空间 '' 不存在

    描述 在使用imp命令将dmp文件导入oracle中时,遇到如下错误: IMP: 遇到 ORACLE 错误 ORA: 表空间 'TBS_CDUSER' 不存在 IMP命令如下: IMP cduser/ ...

  9. J2SE-鸡汤

    前言 终于开始学java了,心里免不了的开心,总是听老乡说他们公司搞java开发,用的什么什么框架,说的自己都有点眼馋了,但是根据自己的性格,不了解它,肯定不会就去用它的.所以在学习框架之前,java ...

  10. loj #547. 「LibreOJ β Round #7」匹配字符串

    #547. 「LibreOJ β Round #7」匹配字符串   题目描述 对于一个 01 串(即由字符 0 和 1 组成的字符串)sss,我们称 sss 合法,当且仅当串 sss 的任意一个长度为 ...