参考文档:
Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例:https://www.cnblogs.com/skywang12345/p/3533995.html
简介
CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。因为该 barrier 在释放等待线程后可以重用,所以称它为循环的 barrier。基于ReentrantLock实现
举个栗子

/*** 简单模拟一下对战平台中玩家需要完全准备好了,才能进入游戏的场景。* * @author BFD_526* */
public class CyclicBarrierTest {public static void main(String[] args) {test();}// 同步屏障static void test() {ExecutorService service = Executors.newFixedThreadPool(5);CyclicBarrier barrier = new CyclicBarrier(5);for (int i = 0; i < 5; i++) {service.execute(new Player("玩家" + i, barrier));}service.shutdown();}// 同步屏障重置static void test1() {ExecutorService service = Executors.newFixedThreadPool(5);CyclicBarrier barrier = new CyclicBarrier(5);for (int i = 0; i < 5; i++) {service.execute(new Player("玩家" + i, barrier));}for (int i = 5; i < 10; i++) {service.execute(new Player("玩家" + i, barrier));}service.shutdown();}// 在同步屏障结束后,启动优先线程static void test2() {ExecutorService service = Executors.newFixedThreadPool(5);CyclicBarrier ba = new CyclicBarrier(5, new Runnable() {@Overridepublic void run() {System.out.println("所有玩家已就位");}});for (int i = 0; i < 5; i++) {service.execute(new Player("玩家" + i, ba));}}
}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 + "离开游戏");}}
}

View Code

源码分析

函数列表

CyclicBarrier(int parties):创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预定义的操作
CyclicBarrier(int parties, Runnable barrierAction):创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行
int await():在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待
int await(long timeout, TimeUnit unit):在所有参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间
int getNumberWaiting():返回当前在屏障处等待的参与者数目
int getParties():返回要求启动此 barrier 的参与者数目
boolean isBroken():查询此屏障是否处于损坏状态
void reset():将屏障重置为其初始状态

await()

public int await() throws InterruptedException, BrokenBarrierException {try {return dowait(false, 0L);} catch (TimeoutException toe) {throw new Error(toe); // cannot happen;
    }
}

private int dowait(boolean timed, long nanos)throws InterruptedException, BrokenBarrierException,TimeoutException {final ReentrantLock lock = this.lock;// 获取“独占锁(lock)”
    lock.lock();try {// 保存“当前的generation”final Generation g = generation;// 若“当前generation已损坏”,则抛出异常。if (g.broken)throw new BrokenBarrierException();// 如果当前线程被中断,则通过breakBarrier()终止CyclicBarrier,唤醒CyclicBarrier中所有等待线程。if (Thread.interrupted()) {breakBarrier();throw new InterruptedException();}// 将“count计数器”-1int index = --count;// 如果index=0,则意味着“有parties个线程到达barrier”if (index == 0) {  // trippedboolean ranAction = false;try {// 如果barrierCommand不为null,则执行该动作final Runnable command = barrierCommand;if (command != null)command.run();ranAction = true;// 唤醒所有等待线程,并更新generation
               nextGeneration();return 0;} finally {if (!ranAction)breakBarrier();}}// 当前线程一直阻塞,直到“有parties个线程到达barrier” 或 “当前线程被中断” 或 “超时”这3者之一发生,// 当前线程才继续执行。for (;;) {try {// 如果不是“超时等待”,则调用awati()进行等待;否则,调用awaitNanos()进行等待if (!timed)trip.await();else if (nanos > 0L)nanos = trip.awaitNanos(nanos);} catch (InterruptedException ie) {// 如果等待过程中,线程被中断,则执行下面的函数if (g == generation && ! g.broken) {breakBarrier();throw ie;} else {Thread.currentThread().interrupt();}}// 如果“当前generation已经损坏”,则抛出异常if (g.broken)throw new BrokenBarrierException();// 如果“generation已经换代”,则返回indexif (g != generation)return index;// 如果是“超时等待”,并且时间已到,则通过breakBarrier()终止CyclicBarrier,唤醒CyclicBarrier中所有等待线程if (timed && nanos <= 0L) {breakBarrier();throw new TimeoutException();}}} finally {// 释放“独占锁(lock)”
        lock.unlock();}
}

generation是CyclicBarrier的一个成员变量,它的定义如下:

private Generation generation = new Generation();private static class Generation {boolean broken = false;
}

在CyclicBarrier中,同一批的线程属于同一代,即同一个Generation;CyclicBarrier中通过generation对象,记录属于哪一代
当有parties个线程到达barrier,generation就会被更新换代
换代:

//换代private void nextGeneration() {trip.signalAll();count = parties;generation = new Generation();
}

private void breakBarrier() {generation.broken = true;count = parties;trip.signalAll();
}

转载于:https://www.cnblogs.com/amei0/p/9021032.html

concurrent(六)同步辅助器CyclicBarrier 源码分析相关推荐

  1. C++Primer Plus (第六版)阅读笔记 + 源码分析【目录汇总】

    C++Primer Plus (第六版)阅读笔记 + 源码分析[第一章:预备知识] C++Primer Plus (第六版)阅读笔记 + 源码分析[第二章:开始学习C++] C++Primer Plu ...

  2. Java并发编程(十六):CyclicBarrier源码分析

    前言   CyclicBarrier可以建立一个屏障,这个屏障可以阻塞一个线程直到指定的所有线程都达到屏障.就像团队聚餐,等所有人都到齐了再一起动筷子.根据Cyclic就可以发现CyclicBarri ...

  3. spring拦截器覆盖_springmvc拦截器及源码分析

    前言 springmvc拦截器是我们项目开发中用到的一个功能,常常用于对Handler进行预处理和后处理.本案例来演示一个较简单的springmvc拦截器的使用,并通过分析源码来探究拦截器的执行顺序是 ...

  4. Linux线程同步(三)---互斥锁源码分析

    先给自己打个广告,本人的微信公众号:嵌入式Linux江湖,主要关注嵌入式软件开发,股票基金定投,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题. 一 源码分析 1.li ...

  5. WPF(六) Command 命令模型源码分析

    1.ICommand源码分析 ​ 在之前 WPF(三) WPF命令 中我们已经分析过了 WPF 的命令系统,包括WPF默认的 RoutedCommand 以及我们自定义的 ICommand 命令实现. ...

  6. CyclicBarrier源码分析

    前言 前面,我们在CountDownLatch和CyclicBarrier那点事中简单介绍了CountDownLatch和CyclicBarrier中的使用小demo,同时比对了这两个线程协作工具的特 ...

  7. Mybatis Interceptor 拦截器原理 源码分析

    Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最 ...

  8. 六、阻塞队列与源码分析(上)

    一.阻塞队列BlockingQueue 1.先理解Queue.Deque 1.Queue(队列):用于保存一组元素,不过在存取元素的时候必须遵循先进先出原则.队列是一种特殊的线性表,它只允许在表的前端 ...

  9. 【java】java 并发编程 CyclicBarrier 源码分析

    文章目录 1.概述 4.源码阅读 4.1 构造方法 4.2 Generation 4.3 属性Condition 4.4 await方法 4.4.1 BrokenBarrierException 4. ...

最新文章

  1. python 获取打印的内容并保存到记事本里面
  2. 怎样做到真实再现传统文化艺术?
  3. 集群的可扩展性及其分布式体系结构(3)--上
  4. php变量有三种不同的作用域,PHP中变量类型与转换,变量的检测以及变量的作用域学习--2018年4月13日12时03分...
  5. n!的分解 soj 2666
  6. 函数式编程和面向对象式编程_比较函数式编程,命令式编程和面向对象的编程
  7. 根据应用场景人工智能技术有哪些分类?
  8. 微软新一代企业应用平台 促进动态IT发展
  9. C++11常用特性的使用经验总结-概述及目录
  10. oracle里的or 短路么,Oracle CASE短路不能分组工作
  11. cocos2dx 圆盘抽奖_Cocos2D-X转盘游戏制作教程:博彩大转盘
  12. TensorFlow Keras 官方文档中文版文档学习
  13. C语言【库函数与自定义函数】详解
  14. 怎么做网站,网站制作步骤有哪些?
  15. python处理word文档格式_python处理word文档(docxtpl 中文说明文档)
  16. 2013年放假安排时间表 法定节假日安排通知 ( IS2120@BG57IV3)
  17. BEVFusion: A Simple and Robust LiDAR-CameraFusion Framework 细读
  18. 输出7和7的倍数,还有包含7的数字例如(17,27,37...70,71,72,73...)
  19. 计算机主机配置一般有机箱主板cpu,组装台式电脑配置清单
  20. CoderForces999C-Alphabetic Removals

热门文章

  1. php实现查询上传文件进度
  2. 有关 Session 操作的几个误区
  3. asp.net控件开发基础(1)
  4. Ubuntu 14.04 LTS, 64bit, cuda 7, Caffe环境配置编译和安装
  5. 自动驾驶进入第3阶段 ADAS黑科技守护开车人
  6. Win7硬盘安装方法
  7. 使用ABAP(ADBC)和Java(JDBC)连接SAP HANA数据库
  8. MySQL 使用自增ID主键和UUID 作为主键的优劣比較具体过程(从百万到千万表记录測试)...
  9. 记一次意外的自定义控件
  10. mongodb学习参考博文