模块 java.base

类 CyclicBarrier

java.lang.Object
java.util.concurrent.CyclicBarrier

public class CyclicBarrier extends Object
允许一组线程全部等待彼此到达公共屏障点的同步辅助工具。 CyclicBarriers 在涉及必须偶尔相互等待的固定大小线程组的程序中很有用。屏障被称为cyclic,因为它可以在等待线程被释放后重新使用。

CyclicBarrier 支持可选的 Runnable 命令,该命令在每个障碍点运行一次,在派对中的最后一个线程到达之后,但在释放任何线程之前。这个 barrier action 对于在任何一方继续之前更新共享状态很有用。

示例用法:以下是在并行分解设计中使用障碍的示例:

 
 class Solver {
  final int N;
  final float[][] data;
  final CyclicBarrier barrier;

  class Worker implements Runnable {
   int myRow;
   Worker(int row) { myRow = row; }
   public void run() {
    while (!done()) {
     processRow(myRow);

     try {
      barrier.await();
     } catch (InterruptedException ex) {
      return;
     } catch (BrokenBarrierException ex) {
      return;
     }
    }
   }
  }

  public Solver(float[][] matrix) {
   data = matrix;
   N = matrix.length;
   Runnable barrierAction = () -> mergeRows(...);
   barrier = new CyclicBarrier(N, barrierAction);

   List<Thread> threads = new ArrayList<>(N);
   for (int i = 0; i < N; i++) {
    Thread thread = new Thread(new Worker(i));
    threads.add(thread);
    thread.start();
   }

   // wait until done
   for (Thread thread : threads)
    try {
     thread.join();
    } catch (InterruptedException ex) { }
  }
 } 
这里,每个工作线程处理矩阵的一行,然后在屏障处等待,直到处理完所有行。处理完所有行后,将执行提供的 Runnable 屏障操作并合并行。如果合并确定已找到解决方案,则 done() 将返回 true 并且每个 worker 将终止。

如果屏障操作不依赖于执行时挂起的各方,则该方中的任何线程都可以在释放时执行该操作。为了促进这一点,await() 的每次调用都会返回该线程在屏障处的到达索引。然后您可以选择哪个线程应该执行屏障操作,例如:

 
 if (barrier.await() == 0) {
  // log the completion of this iteration
 } 

CyclicBarrier 对失败的同步尝试使用全有或无中断模型:如果一个线程由于中断、失败或超时而过早离开障碍点,所有其他在该障碍点等待的线程也将通过 BrokenBarrierException (或 InterruptedException )异常离开如果他们也大约在同一时间被打断)。

内存一致性影响:在调用 await() 发生在之前 操作之前线程中的操作是屏障操作的一部分,这反过来发生在之前从其他线程中相应的 await() 成功返回后的操作。

自从:
1.5
参见:
  • 构造方法总结

    构造方法
    构造方法
    描述
    CyclicBarrier(int parties)
    创建一个新的 CyclicBarrier,它将在给定数量的参与方(线程)等待时触发,并且在障碍触发时不执行预定义的操作。
    CyclicBarrier(int parties, Runnable barrierAction)
    创建一个新的 CyclicBarrier,当给定数量的参与方(线程)等待它时,它将触发,并在触发障碍时执行给定的障碍操作,由进入障碍的最后一个线程执行。
  • 方法总结

    修饰符和类型
    方法
    描述
    int
    等待所有 parties 在此屏障上调用 await
    int
    await(long timeout, TimeUnit unit)
    等待直到所有 parties 在此屏障上调用 await,或者指定的等待时间过去。
    int
    返回当前在屏障处等待的参与方数量。
    int
    返回触发此障碍所需的参与方数量。
    boolean
    查询此屏障是否处于损坏状态。
    void
    将屏障重置为其初始状态。

    在类 java.lang.Object 中声明的方法

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • 构造方法详细信息

    • CyclicBarrier

      public CyclicBarrier(int parties, Runnable  barrierAction)
      创建一个新的 CyclicBarrier,当给定数量的参与方(线程)等待它时,它将触发,并在触发障碍时执行给定的障碍操作,由进入障碍的最后一个线程执行。
      参数:
      parties - 在屏障被触发之前必须调用 await() 的线程数
      barrierAction - 当屏障被触发时执行的命令,或者 null 如果没有动作
      抛出:
      IllegalArgumentException - 如果 parties 小于 1
    • CyclicBarrier

      public CyclicBarrier(int parties)
      创建一个新的 CyclicBarrier,它将在给定数量的参与方(线程)等待时触发,并且在障碍触发时不执行预定义的操作。
      参数:
      parties - 在屏障被触发之前必须调用 await() 的线程数
      抛出:
      IllegalArgumentException - 如果 parties 小于 1
  • 方法详情

    • getParties

      public int getParties()
      返回触发此障碍所需的参与方数量。
      返回:
      突破这一障碍所需的参与方数量
    • await

      public int await() throws InterruptedException , BrokenBarrierException
      等待所有 parties 在此屏障上调用 await

      如果当前线程不是最后一个到达的线程,则出于线程调度目的而禁用它并处于休眠状态,直到发生以下情况之一:

      • 最后一个线程到达;或者
      • 一些其他线程中断当前线程;或者
      • 其他线程 中断 其他等待线程之一;或者
      • 其他线程在等待屏障时超时;或者
      • 一些其他线程在此屏障上调用 reset()

      如果当前线程:

      • 在进入此方法时设置其中断状态;或者
      • 等待时是interrupted
      然后抛出InterruptedException 并清除当前线程的中断状态。

      如果在任何线程等待时屏障为 reset() ,或者在调用 await 时屏障为 被打破,或者在任何线程等待时屏障为 被打破,则抛出 BrokenBarrierException

      如果任何线程在等待时为 interrupted,则所有其他等待线程将抛出 BrokenBarrierException 并将屏障置于中断状态。

      如果当前线程是最后一个到达的线程,并且在构造方法中提供了非空屏障操作,则当前线程在允许其他线程继续之前运行该操作。如果在屏障操作期间发生异常,则该异常将在当前线程中传播,并且屏障将置于中断状态。

      返回:
      当前线程的到达索引,其中索引getParties() - 1表示第一个到达,零表示最后一个到达
      抛出:
      InterruptedException - 如果当前线程在等待时被中断
      BrokenBarrierException - 如果 another 线程在当前线程等待时被中断或超时,或者屏障被重置,或者屏障在调用 await 时被破坏,或者屏障操作(如果存在)由于异常而失败
    • await

      public int await(long timeout, TimeUnit  unit) throws InterruptedException , BrokenBarrierException , TimeoutException
      等待直到所有 parties 在此屏障上调用 await,或者指定的等待时间过去。

      如果当前线程不是最后一个到达的线程,则出于线程调度目的而禁用它并处于休眠状态,直到发生以下情况之一:

      • 最后一个线程到达;或者
      • 指定的超时已过;或者
      • 一些其他线程中断当前线程;或者
      • 其他线程 中断 其他等待线程之一;或者
      • 其他线程在等待屏障时超时;或者
      • 一些其他线程在此屏障上调用 reset()

      如果当前线程:

      • 在进入此方法时设置其中断状态;或者
      • 等待时是interrupted
      然后抛出InterruptedException 并清除当前线程的中断状态。

      如果指定的等待时间过去,则抛出 TimeoutException 。如果时间小于或等于零,则该方法根本不会等待。

      如果在任何线程等待时屏障为 reset() ,或者在调用 await 时屏障为 被打破,或者在任何线程等待时屏障为 被打破,则抛出 BrokenBarrierException

      如果任何线程在等待时为 interrupted,则所有其他等待线程将抛出 BrokenBarrierException 并将屏障置于中断状态。

      如果当前线程是最后一个到达的线程,并且在构造方法中提供了非空屏障操作,则当前线程在允许其他线程继续之前运行该操作。如果在屏障操作期间发生异常,则该异常将在当前线程中传播,并且屏障将置于中断状态。

      参数:
      timeout - 等待屏障的时间
      unit - 超时参数的时间单位
      返回:
      当前线程的到达索引,其中索引getParties() - 1表示第一个到达,零表示最后一个到达
      抛出:
      InterruptedException - 如果当前线程在等待时被中断
      TimeoutException - 如果指定的超时结束。在这种情况下,障碍将被打破。
      BrokenBarrierException - 如果 another 线程在当前线程等待时被中断或超时,或者屏障被重置,或者屏障在调用 await 时被破坏,或者屏障操作(如果存在)由于异常而失败
    • isBroken

      public boolean isBroken()
      查询此屏障是否处于损坏状态。
      返回:
      true如果一方或多方由于构建或上次重置后的中断或超时而突破此屏障,或者屏障操作因异常而失败; false否则。
    • reset

      public void reset()
      将屏障重置为其初始状态。如果目前有任何一方正在屏障处等待,他们将返回 BrokenBarrierException 。请注意,重置 after 由于其他原因发生的破损执行起来可能很复杂;线程需要以其他方式重新同步,并选择一个来执行重置。相反,创建一个新的屏障以供后续使用可能更可取。
    • getNumberWaiting

      public int getNumberWaiting()
      返回当前在屏障处等待的参与方数量。此方法主要用于调试和断言。
      返回:
      当前在 await() 中被阻止的派对数量