目录
3.1:构造函数java.util.concurrent.CyclicBarrier#CyclicBarrier(int,java.lang.Runnable)
1:写在前面
1:CyclicBarrier旨在当n个线程全部阻塞的时候,然后一起运行,或者是执行某一个task
2:架构设计
CyclicBarrier内部使用的是一个ReentrantLock里面的 condition#signalAll();
3:执行流程源码分析
3.1:构造函数java.util.concurrent.CyclicBarrier#CyclicBarrier(int,java.lang.Runnable)
创建一个CyclicBarrier,第一个参数为扣减值,第二个参数为当扣减值==0的时候即将运行的task
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
3.2:线程执行阻塞方法
java.util.concurrent.CyclicBarrier#await()
java.util.concurrent.CyclicBarrier#dowait
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 的时候
if (index == 0) { // tripped
boolean ranAction = false;
try {
//构造函数中传中的barrierAction
final Runnable command = barrierCommand;
//如果传入了就运行这个任务
if (command != null)
command.run();
ranAction = true;
//重置下一次的任务扣减次数---- 这个地方和CountDownLatch的最大的区别
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();
}
}
3.3:唤醒线程
java.util.concurrent.CyclicBarrier#nextGeneration
private void nextGeneration() {
// signal completion of last generation
//唤醒其他的线程
trip.signalAll();
// set up next generation
//初始化下一轮的参数
count = parties;
generation = new Generation();
}
4:总结
- CyclicBarrier内部的同步器实现了ReentrantLock(非公平锁),然后使用了ReentrantLock#condition#signalAll来唤醒其他的线程
-
public ReentrantLock() { sync = new NonfairSync(); }
- 和CountDownLatch的最大的区别是提供了重置的方法,而CountDownLatch只能使用一次,我们可以在CyclicBarrier中使用reset 方法来重置CyclicBarrier
-
public void reset() { final ReentrantLock lock = this.lock; lock.lock(); try { breakBarrier(); // break the current generation nextGeneration(); // start a new generation } finally { lock.unlock(); } }