他的作用时使一组线程到达一个屏障点(也可以叫同步点)时会被阻塞,直到最后同一个线程到达屏障时,屏障就会开门,所以的被拦截的线程才会继续执行。
构造器
public CyclicBarrier(int parties, Runnable barrierAction) {if (parties <= 0) throw new IllegalArgumentException();this.parties = parties;this.count = parties;this.barrierCommand = barrierAction;}
构造器可知CyclicBarrier创建时,会有一个阻塞线程数和一个阻塞后运行的线程。
await()同步点
public int await() throws InterruptedException, BrokenBarrierException {try {return dowait(false, 0L);//nanos时等待时间} 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;//已经执行过到这里的次数,由于这里已经加锁所以不会有并发问题if (index == 0) { // tripped,所以的线程都到了这个屏障点boolean ranAction = false;try {final Runnable command = barrierCommand;//获取屏障CyclicBarrier构造器的线程if (command != null)command.run();//由最后一个线程调用run方法(这里没有新建一个线程)ranAction = true;nextGeneration();return 0;} finally {if (!ranAction)breakBarrier();//破环屏障}}// loop until tripped, broken, interrupted, or timed out 循环直到触发、损坏、中断 或者超时for (;;) {try {if (!timed)//不需要超时等待trip.await();//condition阻塞在这里,让其他线程抢占lockelse 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();}}
可以看出,运行到cyclicbarrier.await()方法后会维护一把重入锁,每个线程进来计算器-1,并通过condition阻止。当计算器=0,及最后一个线程进来的时候,会执行cyclicbarrier的方法。执行完成会调用nextGeneration()唤醒其他所以的线程
private void nextGeneration() {// signal completion of last generationtrip.signalAll();// set up next generationcount = parties;generation = new Generation();}
