CyclicBarrier(回环栅栏)
通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier 可以被重用。我们暂且把这个状态就叫做barrier,当调用 await()方法之后,线程就处于 barrier 了。
await()方法的重载
- public int await():用来挂起当前线程,直至所有线程都到达 barrier 状态再同时执行后续任务;
- public int await(long timeout, TimeUnit unit):让这些线程等待至一定的时间,如果还有线程没有到达 barrier 状态就直接让到达 barrier 的线程执行后续任务。
示例代码
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(2);
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()+"running");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"finish");
},"A").start();
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()+"running");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"finish");
},"B").start();
}
部分源码分析
部分成员变量
private static class Generation {
boolean broken = false;
}
/** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
private final Condition trip = lock.newCondition();
/** The number of parties */
private final int parties;
/* The command to run when tripped */
private final Runnable barrierCommand;
/** The current generation */
private Generation generation = new Generation();
CyclicBarrier是通过ReentrantLock+Condition实现的工具类,里面维护这一个计算器parties来记录个数,当每个线程被barrier.await()时,线程就会被阻塞并且parties会-1操作,当parties变为0时,CyclicBarrier就会唤醒所有线程。
构造函数
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
public CyclicBarrier(int parties) {
this(parties, null);
}