假如说A、B、C、D四个线程需要执行到某一个点,然后一起继续执行,就可以使用CyclicBarrier实现(例如DNF中,所有人都准备好,才能进下一个地图)。
/** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
执行await的线程,会阻塞在上面
private final Condition trip = lock.newCondition();
指定等待的线程数,当有parties个线程await后,所有线程会一起继续执行
private final int parties;
当所有线程都准备好后(有parties个线程执行await),会执行该线程
private final Runnable barrierCommand;
cyclicBarrier 每次循环使用,都会重新生成
private Generation generation = new Generation();
未执行await的线程数
private int count;
构造函数,需要指定线程个数和栅栏放开时执行的线程(可为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;
index=0,说明所有线程都已执行await方法
if (index == 0) { // tripped
boolean ranAction = false;
try {
如果构造函数中指定了线程,此时会执行该线程
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
这里会重新初始化cyclicBarrier,可以循环使用,并且唤醒所有阻塞的线程
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
for (;;) {
try {
是否指定超时,未指定超时则永久await,直到被唤醒或被中断
if (!timed)
trip.await();
如果指定超时时间,会阻塞nanos纳秒
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();
被唤醒的线程会判断是否cyclicBarrier进入下一个循环,不等于说明cyclicBarrier被重置,线程可以继续向后执行了
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
当线程中断时,执行该方法,表明当前cyclicBarrier已被中断,对broken进行置位为true,唤醒阻塞线程
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
await
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
把线程节点放入condition队列
Node node = addConditionWaiter();
将锁释放掉,cas减去state
int savedState = fullyRelease(node);
int interruptMode = 0;
判断节点是否第一次进入condition队列中,如果是第一次,就阻塞等待唤醒
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
getNumberWaiting
public int getNumberWaiting() {
该方法会返回阻塞的线程数
final ReentrantLock lock = this.lock;
lock.lock();
try {
线程总数-未进行await的线程数
return parties - count;
} finally {
lock.unlock();
}
}