CyclicBarrier允许一组线程互相等待,直到到达某个公共屏障点。如果你希望一组并行的任务在下个步骤之前相互等待,直到所有的任务都完成了下个步骤前的所有操作,才继续向前执行,那么CyclicBarrier很合适。
函数列表
//构造方法摘要
CyclicBarrier(int parties)
//创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预定义的操作。
CyclicBarrier(int parties, Runnable barrierAction)
//创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行。
//方法摘要
int await()
//在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
int await(long timeout, TimeUnit unit)
//在所有参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间。
int getNumberWaiting()
//返回当前在屏障处等待的参与者数目。
int getParties()
//返回要求启动此 barrier 的参与者数目。
boolean isBroken()
//查询此屏障是否处于损坏状态。
void reset()
//将屏障重置为其初始状态。
CyclicBarrier与CountDownLatch的比较
看过CyclicBarrier的方法列表后,有没有发现CyclicBarrier与CountDownLatch比较像。它们之间最大的区别在于CyclicBarrier的计数器可以重置,相当于可以循环使用。cyclic,意为可循环的,barrier,意为屏障,刚好映照了CyclicBarrier的两个特点。
实例1:CyclicBarrier简单使用
public class CyclicBarrierTest {
// 参与者数量
private static int parties = 3;
// 创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动
private static CyclicBarrier barrier = new CyclicBarrier(parties);
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < parties; i++)
new Thread(new Task()).start();
Thread.sleep(1000);
System.out.println("getNumberWaiting():" + barrier.getNumberWaiting());
}
static class Task implements Runnable {
public void run() {
try {
System.out.println(Thread.currentThread().getName() + "await");
// 在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
barrier.await();
System.out.println(Thread.currentThread().getName() + "continued");
} catch (BrokenBarrierException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果为:
Thread-0await
Thread-1await
Thread-2await
Thread-1continued
Thread-0continued
Thread-2continued
getNumberWaiting():0
从结果中可以看到,3个任务线程依次启动,但每一个都没有执行完,这是因为run方法中的cb.await();
使当前线程在所有参与者都已经在此barrier上调用await方法之前,一直等待。直到所有的参与者都已经在此barrier上调用await,才执行所有等待的任务。
从最后一行输出可以看出,在所有线程越过屏障后,当前在屏障处等待的参与者数目变为0。
源码
待补充
本文就讲到这里,想了解Java并发编程更多内容请参考:
- Java并发编程札记-目录