CyclicBarrier分析
简介
- CyclicBarrier 是什么?
- CyclicBarrier 使用
- CyclicBarrier 源码解析
- CyclicBarrier 简单实现
- barrierAction 是由哪个线程执行的?
CyclicBarrier 是什么?
CyclicBarrier 开始于JDK 1.5, 一个同步工具类,允许一组线程都等待彼此到达公共屏障点。CyclicBarrier 在程序中非常有用,涉及到固定参数的线程数量等待彼此,这个 barrier 被称为
cyclic 是由于它可以所有的等待线程释放之后,重复使用。
CyclicBarrier 支持一个可选的 Runnable 在每一个屏障点执行一次,在所有参与的线程到达之后,但是在执行之前所有的线程都释放了, barrierAction非常有用的对于在任何参与者继续之前更新共享状态。
CyclicBarrier 使用
public class Test2 {
static class A extends Thread {
private CyclicBarrier cyclicBarrier;
public A(CyclicBarrier cyclicBarrier, String name) {
this.cyclicBarrier = cyclicBarrier;
setName(name);
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " 准备完毕");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
static class B extends Thread {
private CyclicBarrier cyclicBarrier;
public B(CyclicBarrier cyclicBarrier, String name) {
this.cyclicBarrier = cyclicBarrier;
setName(name);
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " 准备完毕");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
static class C extends Thread {
private CyclicBarrier cyclicBarrier;
public C(CyclicBarrier cyclicBarrier, String name) {
this.cyclicBarrier = cyclicBarrier;
setName(name);
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " 准备完毕");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> System.out.println("完成"));
new A(cyclicBarrier, "A").start();
new B(cyclicBarrier, "B").start();
new C(cyclicBarrier, "C").start();
}
}
/**
output:
A 准备完毕
B 准备完毕
C 准备完毕
完成
*/
CyclicBarrier 源码解析
在看源码前,我们可以对源码的实现进行一些猜想,根据 CyclicBarrier 前面的定义,可以猜想里面有一个变量来表示参与者的数量,在使用调用 await 方法是时候,参与者的数量减一,
知道参与者数量为 0,存在 barrierAction,就执行barrierAction,由于可以重复使用,所以在barrierAction执行对参与者的数量进行恢复。
下面看一下源码实现是否于猜想的类似。
构造方法
parties 参与者的数量
barrierAction 最后执行的动作(可选)
public CyclicBarrier(int parties) {
this(parties, null);
}
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
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();
try {
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
// 减去一个参与者
int index = --count;
// 如果参与者数量为0,判断barrierAction是否为null,不为null, 将执行run方法,调用nextGeneration恢复状态
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
trip.await(); // 在屏障点等待
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
nextGeneration 方法
private void nextGeneration() {
// signal completion of last generation
trip.signalAll(); // 唤醒参与者
// set up next generation
count = parties; // 恢复参与者的数量
generation = new Generation(); // 下一代
}
CyclicBarrier 简单实现
借助AtomicInteger 来简单实现
public class SimpleBarrier {
private AtomicInteger count;
int size;
private Runnable command;
public SimpleBarrier(int n) {
this.count = new AtomicInteger(n);
this.size = n;
}
public SimpleBarrier(int n, Runnable barrierAction) {
this(n);
this.command = barrierAction;
}
public void await() {
int position = count.getAndDecrement();
if (position == 1) {
command.run();
count.set(size);
} else {
while (count.get() != 0) {
}
}
}
}
public class Test2 {
static class A extends Thread {
private SimpleBarrier cyclicBarrier;
public A(SimpleBarrier cyclicBarrier, String name) {
this.cyclicBarrier = cyclicBarrier;
setName(name);
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 准备完毕");
cyclicBarrier.await();
}
}
static class B extends Thread {
private SimpleBarrier cyclicBarrier;
public B(SimpleBarrier cyclicBarrier, String name) {
this.cyclicBarrier = cyclicBarrier;
setName(name);
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 准备完毕");
cyclicBarrier.await();
}
}
static class C extends Thread {
private SimpleBarrier cyclicBarrier;
public C(SimpleBarrier cyclicBarrier, String name) {
this.cyclicBarrier = cyclicBarrier;
setName(name);
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 准备完毕");
cyclicBarrier.await();
}
}
public static void main(String[] args) {
SimpleBarrier cyclicBarrier = new SimpleBarrier(3, () -> System.out.println("完成"));
new A(cyclicBarrier, "A").start();
new B(cyclicBarrier, "B").start();
new C(cyclicBarrier, "C").start();
}
}
/**
output:
A 准备完毕
B 准备完毕
C 准备完毕
完成
*/
barrierAction 是由哪个线程执行的?
最后一个线程来执行。
CyclicBarrier分析的更多相关文章
- CyclicBarrier分析与实例
一,介绍 CyclicBarrier是一个保持多个线程共享同一个状态的工具类. 也就是说在多线程环境下,能够通过设定某一个状态来达到线程之间的同步.这个类有两个有參构造方法.各自是CyclicBar ...
- 【Java并发编程实战】-----“J.U.C”:CyclicBarrier
在上篇博客([Java并发编程实战]-----"J.U.C":Semaphore)中,LZ介绍了Semaphore,下面LZ介绍CyclicBarrier.在JDK API中是这么 ...
- 【JUC】JDK1.8源码分析之CyclicBarrier(四)
一.前言 有了前面分析的基础,现在,接着分析CyclicBarrier源码,CyclicBarrier类在进行多线程编程时使用很多,比如,你希望创建一组任务,它们并行执行工作,然后在进行下一个步骤之前 ...
- Java 线程同步组件 CountDownLatch 与 CyclicBarrier 原理分析
1.简介 在分析完AbstractQueuedSynchronizer(以下简称 AQS)和ReentrantLock的原理后,本文将分析 java.util.concurrent 包下的两个线程同步 ...
- 并发编程(七)——AbstractQueuedSynchronizer 之 CountDownLatch、CyclicBarrier、Semaphore 源码分析
这篇,我们的关注点是 AQS 最后的部分,共享模式的使用.本文先用 CountDownLatch 将共享模式说清楚,然后顺着把其他 AQS 相关的类 CyclicBarrier.Semaphore 的 ...
- Java并发编程笔记之CyclicBarrier源码分析
JUC 中 回环屏障 CyclicBarrier 的使用与分析,它也可以实现像 CountDownLatch 一样让一组线程全部到达一个状态后再全部同时执行,但是 CyclicBarrier 可以被复 ...
- 【JUC】JDK1.8源码分析之CyclicBarrier
一.前言 有了前面分析的基础,现在,接着分析CyclicBarrier源码,CyclicBarrier类在进行多线程编程时使用很多,比如,你希望创建一组任务,它们并行执行工作,然后在进行下一个步骤之前 ...
- 并发编程之 CyclicBarrier 源码分析
前言 在之前的介绍 CountDownLatch 的文章中,CountDown 可以实现多个线程协调,在所有指定线程完成后,主线程才执行任务. 但是,CountDownLatch 有个缺陷,这点 JD ...
- Java - "JUC" CyclicBarrier源码分析
Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例 CyclicBarrier简介 CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 ...
随机推荐
- Mariadb3—多表查询
1.内关联 select 字段名 from 表名1 inner join 表名2 on 表名1.字段名=表名2.字段名 where 条件 2.左关联 select 字段名 from 表名1 left ...
- vue Element-ui 表格多选 修改选中行背景色
实现的效果: 整体思路方式: 1.给获取到的数据添加自定义的className 2.在点击行(row-click)和手动点击勾选框的事件(select-all)中获取到当前的row的className ...
- GridSearchCV 参数
GridSearchCV(estimator, param_grid, scoring=None, fit_params=None, n_jobs=1, iid=True, refit=True, c ...
- hdu1671 字典树记录前缀出现次数
题意: 给你一堆电话号,问你这些电话号后面有没有相互冲突的,冲突的条件是当前这个电话号是另一个电话号的前缀,比如有 123456789 123,那么这两个电话号就冲突了,直接输出NO. 思 ...
- POJ 1201 差分约束(集合最小元素个数)
题意: 给你一个集合,然后有如下输入,a ,b ,c表示在范围[a,b]里面有至少有c个元素,最后问你整个集合最少多少个元素. 思路: 和HDU1384一模一样,首先这个题目可 ...
- PAT 乙级 -- 1002 -- 写出这个数
题目: 读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式:每个测试输入包含1个测试用例,即给出自然数n的值.这里保证n小于10100. 输出格式:在一行内输出n的各位数字 ...
- 路由选择协议(RIP/OSPF)
目录 IGP RIP协议 OSPF协议 IS-IS协议 EIGRP协议 EGP BGP 我们可能会想,在偌大的网络中,我们是如何跟其他人通信的呢?我们是如何跟远在太平洋对面的美国小伙伴对话的呢? 这就 ...
- Windows PE资源表编程(枚举资源树)
资源枚举 写一个例子,枚举一个PE文件的资源表.首先说下资源相关的作为铺垫. 1.资源类型也是PE可选头中数据目录的一种.位于第三个类型. 2.资源目录分为三层.第四层是描述文件相关的.这些结构是按照 ...
- big data-1
- css 实现三角形
#demo1 { width: 0; height: 0; border-top: 100px solid rgba(255, 0, 0, 1); border-bottom: 50px solid ...