本文代码基于Java8
前言
CyclicBarrier
字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier
可以被重用。
CyclicBarrier类结构
CyclicBarrier
底层使用重写锁和 Generation
实现,源码如下:
1 | public class CyclicBarrier { |
使用示例
一群学生准备乘车出去玩,约定明天在学校门口集合上车出发。现在陆陆续续的一个一个同学上车了,如果还有学生没到,其它人都必须等待。
1 | private final static int NUM = 3; |
执行结果如下:
1 | Thread-0 出发! |
构造函数
1 | /** |
await 方法
等待直到在这个 barrier 中有 parties 个线程调用了 await 方法。如果当前线程不是最后一个到达的,则由于线程调度的原因被禁用,sleep 直至以下事情发生:
- 最后一个线程的到达;
- 其它的线程中断了当前线程;
- 其它的线程中断了和一样正在等待的线程;
- 其它线程等待barrier超时;
- 其它线程在这个barrier处调用了reset方法。
1 | public int await() throws InterruptedException, BrokenBarrierException { |
此方法是本质上是调用 dowait 方法来完成,dowait 方法实现如下:
1 | private int dowait(boolean timed, long nanos) |
breakBarrier()
和 nextGeneration()
实现如下:
1 | // 设置当前的generation状态为broken且唤醒所有正在等待的线程。 |
总结
- CyclicBarrier 是可重用的,CountDownLatch 是不可重用的。
- CyclicBarrier 的用途是让一组线程互相等待,直到到达某个公共屏障点才开始继续工作。
- CyclicBarrier 指定的任务是进入 barrier 最后一个线程来调用的,如果在执行这个任务发生异常时,则会传播到此线程,其它线程不受影响继续正常运行。
- 在等待的只要有一个线程发生中断,则其它线程就会被唤醒继续正常运行。