模块  java.base
软件包  java.util.concurrent

Class CyclicBarrier


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

    CyclicBarrier支持可选的Runnable命令,该命令在每个障碍点运行一次,在聚会中的最后一个线程到达之后,但在释放任何线程之前。 在任何一方继续之前,此屏障操作对于更新共享状态非常有用。

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

       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) thread.join(); } } 
    这里,每个工作线程处理一行矩阵,然后在屏障处等待,直到所有行都被处理完毕。 处理完所有行后,将执行提供的Runnable屏障操作并合并行。 如果合并确定已找到解决方案,则done()将返回true并且每个工作人员将终止。

    如果屏障操作不依赖于在执行时被暂停的各方,那么该方中的任何线程都可以在其被释放时执行该操作。 为方便起见 ,每次调用await()都会返回该线程在屏障处的到达索引。 然后,您可以选择应执行屏障操作的线程,例如:

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

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

    内存一致性效果:在调用await()之前的线程中的操作happen-before作为屏障操作的一部分的操作,该操作又发生在从其他线程中的相应await()成功返回之后的操作之前

    从以下版本开始:
    1.5
    另请参见:
    CountDownLatch
    • 构造方法摘要

      构造方法  
      构造器 描述
      CyclicBarrier​(int parties)
      创建一个新的 CyclicBarrier ,当给定数量的参与方(线程)等待它时将跳闸,并且当屏障被触发时不执行预定义的操作。
      CyclicBarrier​(int parties, Runnable barrierAction)
      创建一个新的 CyclicBarrier ,当给定数量的参与方(线程)等待它时将跳闸,并且当屏障被触发时执行给定的屏障操作,由进入屏障的最后一个线程执行。
    • 构造方法详细信息

      • 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

        如果当前线程不是最后到达的线程,那么它将被禁用以进行线程调度,并且在发生以下任何一种情况之前处于休眠状态:

        • 最后一个帖子到了; 要么
        • 其他一些线程interrupts当前线程; 要么
        • 其他一些线程interrupts其中一个等待线程; 要么
        • 其他一些线程在等待障碍时超时; 要么
        • 其他一些线程在此屏障上调用reset()

        如果当前线程:

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

        如果障碍是reset() ,而任何线程处于等待状态,或者如果屏障is brokenawait被调用,或在任何线程处于等待状态,然后BrokenBarrierException被抛出。

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

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

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

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

        如果当前线程不是最后到达的线程,那么它将被禁用以进行线程调度,并且在发生以下任何一种情况之前处于休眠状态:

        • 最后一个帖子到了; 要么
        • 指定的超时时间过去了; 要么
        • 其他一些线程interrupts当前线程; 要么
        • 其他一些线程interrupts其他等待线程之一; 要么
        • 其他一些线程在等待障碍时超时; 要么
        • 其他一些线程在此障碍上调用reset()

        如果当前线程:

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

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

        如果障碍是reset() ,而任何线程处于等待状态,或者如果屏障is brokenawait被调用,或在任何线程处于等待状态,然后BrokenBarrierException被抛出。

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

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

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

        public boolean isBroken()
        查询此屏障是否处于损坏状态。
        结果
        true如果一方或多方因施工或上次重置造成的中断或超时,或由于例外导致屏障行动失败而突然出现此障碍; 否则为false
      • reset

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

        public int getNumberWaiting()
        返回当前在屏障处等待的方数。 此方法主要用于调试和断言。
        结果
        目前在 await()被阻止的各方数量