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. oracle创建数据库的语句

    首先 oracle严格来说表空间的概念和数据库的概念很像,为了理解的方便我们,可以把表空间就先当成数据库 我们在安装oracle的服务端的时候默认会安装一些,默认实例 1.建立表空间,现在解释下面语句 ...

  2. Linux问题FAQ1

    1.使用vi编辑器时候,按方向键会产生A,B,C之类的 解决办法:ubuntu server 8.04, vim版本为 7.1.138,客户端使用pietty.vim 在插入模式下, 方向键被转为A ...

  3. Entity Framework Tutorial Basics(35):Local Data

    Local Data The Local property of DBSet provides simple access to the entities that are currently bei ...

  4. 面试经常问的一个问题:final、finalize、finally

    http://m.blog.csdn.net/u010980446/article/details/51493658

  5. easyUI datagrid 分页参数page和rows

    Struts2获取easyUI datagrid 分页参数page和rows 用pageHelper分页时,只要是能够获取前台传来的两个参数page和rows基本就完成了很大一部分. 获取方法:定义两 ...

  6. 自动化打包资源混淆集成python实践----打包

    1.自动化打包方案 1)友盟多渠道多渠道打包 2)gradle productFlavors系统的条件编译 3)美团打包 4)APK文件注释写入渠道号 2.各打包方案简介 1)友盟多渠道多渠道打包(w ...

  7. 源码方式安装rabbitmq

    由于工作环境中属于内网,yum安装方式不可用,所以需要采用源码进行rabbitmq的安装.rabbitmq是基于erlang环境进行运行的,所以需要先按照erlang环境,才能运行rabbitmq-s ...

  8. flask + pymysql操作Mysql数据库

    安装flask-sqlalchemy.pymysql模块 pip install flask-sqlalchemy pymysql ### Flask-SQLAlchemy的介绍 1. ORM:Obj ...

  9. 基于vue实现上下滑动翻页效果

    18年年底的时候,一直在做年度报告的H5页面,因为项目需要,需要实现上下滑动翻页,并且上滑的页面比正常页面的比例要缩小一定比例. 效果类似于http://www.17sucai.com/pins/de ...

  10. HashMap resize导致死循环

    原文链接:https://blog.csdn.net/hll174/article/details/50915346 问题的症状 从前我们的Java代码因为一些原因使用了HashMap这个东西,但是当 ...