1.使用

有时候多个线程可能需要相互等待对方执行到代码中的某个地方(集合点),这时这些线程才能够继续执行 。JDK 1.5 开始引入了一个类java.util.concurrent.CyclicBarrier, 该类可以用来实现这种等待。使用CyclicBarrier实现等待的线程被称为参与方 (Party)。参与方只需要执行CyclicBarrier.await() 就可以实现等待。尽管从应用代码的角度来看,参与方是并发执行CyclicBarrier.await() 的。但是, CyclicBarrier 内部维护了一个显式锁,这使得其总是可以在所有参与方中区分出一个最后执行CyclicBarrier.await()的线程,该线程被称为最后一个线程。除最后一个线程外的任何参与方执行 CyclicBarrier.await()都会导致该线程被暂停(线程生命周期状态变为 WAITING)。 最后一个线程执行 CyclicBarrier.await()会使得使用相应 CyclicBarrie 实例的其他所有参与方被唤醒,而最后一个线程自身并不会被暂停。与CountDownLatch不同的是,CyclicBarrier 实例是可重复使用的:所有参与方被唤醒的时候,任何线程再次执行 CyclicBarrier.await()又会被暂停,直到这些线程中的最后一个线程执行了CyclicBarrier.await() 。
CyclicBarrier的其中一个构造器允许我们指定一个被称为barrierAction 的任务 (Runnable 接口实例)。barrierAction会被最后一个线程执行CyclicBarrier. await方法时执行,该任务执行结束后其他等待线程才会被唤醒。

2.CyclicBarrier的典型应用场景

  • 使迭代 (Iterative) 算法并发化。在并发化的迭代算法中,迭代操作是由多个工作者线程并行执行的。CyclicBarrier可用来实现执行迭代操作的任何一个工作者线程必须等待其他工作者线程也完成当前迭代操作的情况下才继续其下一轮的迭代操作,以便形成迭代操作的中间结果作为下一轮迭代的基础(输入)。因此,该应用场景从代码上反映出来的是, CyclicBarrier.await()调用是在一个循环中执行的。
  • 在测试代码中模拟高并发。在编写多线程程序的测试代码时,我们常常需要使用有限的工作者线程来模拟高并发操作。为此,CyclicBarrier可用来实现这些工作者线程中的任意一个线程在执行其操作前必须等待其他线程也准备就绪,即使得这些工作者线程尽可能地在同一时刻开始其操作。