CyclicBarrier可以称为循环栅栏,也是一个线程同步工具,在所有线程到达barrier之前,线程需要等待。

CyclicBarrier的必需参数为parties,可以称为同伴(线程)的数量:

CyclicBarrier cyclicBarrier = new CyclicBarrier(10);		

当线程调用await()时,表示线程已到达,如果所有线程都已到达,则所有线程继续向后执行,否则线程等待,直到:

  • 最后一个线程到达
  • 等待中的某个线程被中断
  • 等待中的某个线程在等待的过程中超时
  • 等待中的某个线程调用了CyclicBarrierreset()方法

如果某个等待的线程被中断,则所有其它等待的线程都会抛出BrokenBarrierException

构造CyclicBarrier时还可以带第二个参数,是一个Runnable,即当所有线程都到达barrier时,需要执行的操作。

CyclicBarrier cyclicBarrier = new CyclicBarrier(10, action);

该操作由最后一个到达barrier的线程会执行,当它执行完之后,其它等待的线程才被允许继续执行。

CyclicBarrier被称为循环栅栏,是因为它是可以循环使用的。

实现:

  • 使用两个变量parties和count保存barrier关联的线程数量,parties用于barrier重复利用时重置线程数,而count用于记录到达barrier的线程的数量,当线程调用await()时,count的值递减,当count的值为0时,表示barrier完成,
  • 线程调用await(),需要加锁,使用ReentrantLock实现。count递减,并判断是否为0:
    • 如果此时count为0,首先如果Runnable不为空,则在当前线程中执行。然后开始新的barrier循环(先将所有等待的线程唤醒,然后使用parties重置count。)
    • 如果count不为0,当前线程等待。