前言
之前简介了一下countDownLatch,这篇再简单介绍下CyclicBarrier。
区别
CountDownLatch 适用于一组线程和另一个主线程之间的工作协作。一个主线程等待一组工作线程的任务完毕才继续它的执行是使用 CountDownLatch 的主要场景;CyclicBarrier 用于一组或几组线程,比如一组线程需要在一个时间点上达成一致,例如同时开始一个工作。另外,CyclicBarrier 的循环特性和构造函数所接受的 Runnable 参数也是 CountDownLatch 所不具备的。
可能有点拗口吧,画个图大概表示一下。
countDownLatch:
等待一组任务结束之后,然后再继续执行下面的任务。
而CyclicBarrier:
等待一组任务的结束之后,这组任务继续他们各自的任务。
代码实例:
static final Integer LENGTH = 3;
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(LENGTH, new Runnable() {
@Override
public void run() {
System.out.println("all is ok now you can do next thing");
}
});
for (int i = 0; i < LENGTH; i++) {
new Work(i, cyclicBarrier).start();
}
}
static class Work extends Thread {
int index;
CyclicBarrier cyclicBarrier;
public Work(int index, CyclicBarrier cyclicBarrier) {
this.index = index;
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println("线程" + index + "正工作");
try {
Thread.sleep(new Random().nextInt(2000) + 500);
System.out.println("线程" + index + "完成工作,等待新工作");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("线程" + index + "开始新工作啦!!");
}
}
执行结果:
线程0正工作
线程2正工作
线程1正工作
线程1完成工作,等待新工作
线程0完成工作,等待新工作
线程2完成工作,等待新工作
all is ok now you can do next thing
线程2开始新工作啦!!
线程1开始新工作啦!!
线程0开始新工作啦!!
因此可以看出,他的流程是,一组线程的各个线程开启自己的工作,然后进入cyclicBarrier的阻塞状态,等待这组所有的线程都执行完毕后,再各自开启自己的后续流程。
异常:
CyclicBarrier.await() 方法会抛出一个独有的 BrokenBarrierException。这个异常发生在当某个线程在等待本 CyclicBarrier 时被中断或超时或被重置时,其它同样在这个 CyclicBarrier 上等待的线程便会收到BrokenBarrierException。用于告知当前已中断,然后可以根据业务继续执行,或终止。