concurrent(六)同步辅助器CyclicBarrier 源码分析
参考文档:
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 源码分析相关推荐
- C++Primer Plus (第六版)阅读笔记 + 源码分析【目录汇总】
C++Primer Plus (第六版)阅读笔记 + 源码分析[第一章:预备知识] C++Primer Plus (第六版)阅读笔记 + 源码分析[第二章:开始学习C++] C++Primer Plu ...
- Java并发编程(十六):CyclicBarrier源码分析
前言 CyclicBarrier可以建立一个屏障,这个屏障可以阻塞一个线程直到指定的所有线程都达到屏障.就像团队聚餐,等所有人都到齐了再一起动筷子.根据Cyclic就可以发现CyclicBarri ...
- spring拦截器覆盖_springmvc拦截器及源码分析
前言 springmvc拦截器是我们项目开发中用到的一个功能,常常用于对Handler进行预处理和后处理.本案例来演示一个较简单的springmvc拦截器的使用,并通过分析源码来探究拦截器的执行顺序是 ...
- Linux线程同步(三)---互斥锁源码分析
先给自己打个广告,本人的微信公众号:嵌入式Linux江湖,主要关注嵌入式软件开发,股票基金定投,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题. 一 源码分析 1.li ...
- WPF(六) Command 命令模型源码分析
1.ICommand源码分析 在之前 WPF(三) WPF命令 中我们已经分析过了 WPF 的命令系统,包括WPF默认的 RoutedCommand 以及我们自定义的 ICommand 命令实现. ...
- CyclicBarrier源码分析
前言 前面,我们在CountDownLatch和CyclicBarrier那点事中简单介绍了CountDownLatch和CyclicBarrier中的使用小demo,同时比对了这两个线程协作工具的特 ...
- Mybatis Interceptor 拦截器原理 源码分析
Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最 ...
- 六、阻塞队列与源码分析(上)
一.阻塞队列BlockingQueue 1.先理解Queue.Deque 1.Queue(队列):用于保存一组元素,不过在存取元素的时候必须遵循先进先出原则.队列是一种特殊的线性表,它只允许在表的前端 ...
- 【java】java 并发编程 CyclicBarrier 源码分析
文章目录 1.概述 4.源码阅读 4.1 构造方法 4.2 Generation 4.3 属性Condition 4.4 await方法 4.4.1 BrokenBarrierException 4. ...
最新文章
- python 获取打印的内容并保存到记事本里面
- 怎样做到真实再现传统文化艺术?
- 集群的可扩展性及其分布式体系结构(3)--上
- php变量有三种不同的作用域,PHP中变量类型与转换,变量的检测以及变量的作用域学习--2018年4月13日12时03分...
- n!的分解 soj 2666
- 函数式编程和面向对象式编程_比较函数式编程,命令式编程和面向对象的编程
- 根据应用场景人工智能技术有哪些分类?
- 微软新一代企业应用平台 促进动态IT发展
- C++11常用特性的使用经验总结-概述及目录
- oracle里的or 短路么,Oracle CASE短路不能分组工作
- cocos2dx 圆盘抽奖_Cocos2D-X转盘游戏制作教程:博彩大转盘
- TensorFlow Keras 官方文档中文版文档学习
- C语言【库函数与自定义函数】详解
- 怎么做网站,网站制作步骤有哪些?
- python处理word文档格式_python处理word文档(docxtpl 中文说明文档)
- 2013年放假安排时间表 法定节假日安排通知 ( IS2120@BG57IV3)
- BEVFusion: A Simple and Robust LiDAR-CameraFusion Framework 细读
- 输出7和7的倍数,还有包含7的数字例如(17,27,37...70,71,72,73...)
- 计算机主机配置一般有机箱主板cpu,组装台式电脑配置清单
- CoderForces999C-Alphabetic Removals
热门文章
- php实现查询上传文件进度
- 有关 Session 操作的几个误区
- asp.net控件开发基础(1)
- Ubuntu 14.04 LTS, 64bit, cuda 7, Caffe环境配置编译和安装
- 自动驾驶进入第3阶段 ADAS黑科技守护开车人
- Win7硬盘安装方法
- 使用ABAP(ADBC)和Java(JDBC)连接SAP HANA数据库
- MySQL 使用自增ID主键和UUID 作为主键的优劣比較具体过程(从百万到千万表记录測试)...
- 记一次意外的自定义控件
- mongodb学习参考博文