CyclicBarrier 相对于CountDownLatch来讲其源码是简单多了,CountDownlatch的使用场景一般是一等多,CyclicBarrier的使用场景为多个线程互相等待,当然对CountDownLatch有兴趣的博友可以看一下我这篇博客对于CountDownlatch源码的分析https://blog.csdn.net/qq_32459653/article/details/81486757 , 接下来就让我们看下基于JDK1.8的CycliBarrier的实现,其源代码如下,结合我旁边写的注释相信很容易就能看懂
//CyclicBarrrier相对来讲较为简单
package java.util.concurrent;
import java.util.concurrent.locks.*;
* @since 1.5
* @see CountDownLatch
*
* @author Doug Lea
*/
public class CyclicBarrier {
// 当前的Generation。每当屏障失效或者开闸之后都会自动替换掉。从而实现重置的功能。
private static class Generation {
boolean broken = false; //表明是否被破坏
}
// 直间使用重入锁,
private final ReentrantLock lock = new ReentrantLock();
//通过lock获取一个condition条件
private final Condition trip = lock.newCondition();
private final int parties; //表示等待的线程数
//开闸后执行的runnable,可以为空
private final Runnable barrierCommand;
private Generation generation = new Generation();
/**
* Number of parties still waiting. Counts down from parties to 0
* on each generation. It is reset to parties on each new
* generation or when broken.
*/
//表示当前还需多少线程到达
private int count;
/**
* Updates state on barrier trip and wakes up everyone.
* Called only while holding lock.
*/
private void nextGeneration() {
// signal completion of last generation
trip.signalAll(); //唤醒所有线程
// set up next generation
count = parties; //重置count
generation = new Generation(); //
}
/**
* Sets current barrier generation as broken and wakes up everyone.
* Called only while holding lock.
*/
private void breakBarrier() { //打破屏障
generation.broken = true;
count = parties;
trip.signalAll(); //唤醒所有等待的线程
}
/**
* Main barrier code, covering the various policies.
*/
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock(); 加锁
try {
final Generation g = generation;//标记当前的generation
//这里直接抛出异常,如果有其他线程等待那其他线程是否会无限等待呢,答案是否定的,因为broken只能通过breakBarrier()
//方法去破坏(私有方法),而在breakBarrier()方法中会唤醒所有线程,因此,g.broken为true,必定调用了breakBarrier方法,无
//需担心线程会无限等待
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) { //线程被中断
breakBarrier(); //线程被中断,调用此方法表明被皮欢
throw new InterruptedException();
}
int index = --count; //当前count数量减一,因为当前线程到达
if (index == 0) { // tripped
boolean ranAction = false; //标志 用于判断构造参数传入的barrierCommand是否出现异常
try {
final Runnable command = barrierCommand;
if (command != null) //不为空,说明用户传入
command.run();
ranAction = true; //进入这里说明没出现异常
nextGeneration(); //重置,重置时会唤醒所有等待的线程,方法上面已近解释过
return 0;
} finally {
if (!ranAction) //ranAction为false,说明command运行时出现异常,
breakBarrier(); //调用此方法说明屏障被破坏
}
}
// loop until tripped, broken, interrupted, or timed out
for (;;) { //index不为0,会进入这里 ,无限循环
try {
if (!timed) //如果没有定时
trip.await(); //一直等待
else if (nanos > 0L) //给定了时间
nanos = trip.awaitNanos(nanos); //等待给定的时间后,重新唤醒,参与锁的竞争
} catch (InterruptedException ie) {//出现异常
if (g == generation && ! g.broken) { //g还是当前的generaton,且屏障没有被打破
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) //判断是否退出无限循环的标志 ,有两种情况会退出,第一种调用reset方法重 // 置 第二种是最后一个线程到达, 进入index等于0 那块的逻辑代码,满足条件从而退出,该判断专门为timed //等于true时而设置的,因为为false时会无限等待 //直到最后一个线程到达被唤醒,而有时等待会中途唤醒,需 //要判断是否完成
return index;
if (timed && nanos <= 0L) //超时
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
icBarrier(int parties) {
this(parties, null);
}
public int getParties() {
return parties;
}
//线程 无限等待版
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L); //
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen;
}
}
//线程有限制时间 等待版
public int await(long timeout, TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException {
return dowait(true, unit.toNanos(timeout));
}
//判断是否被打破
public boolean isBroken() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return generation.broken;
} finally {
lock.unlock();
}
}
//重置
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // break the current generation
nextGeneration(); // start a new generation
} finally {
lock.unlock();
}
}
//获取已到达,且正在等待的线程数
public int getNumberWaiting() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return parties - count;
} finally {
lock.unlock();
}
}
}