Module  java.base
软件包  java.util.concurrent

Class CyclicBarrier



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

    A 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对失败的同步尝试使用all-or-none断裂模型:如果线程由于中断,故障或超时而过早离开障碍点,则在该障碍点等待的所有其他线程也将异常通过BrokenBarrierException (或InterruptedException如果他们也在同一时间被打断)。

    内存一致性效应:在调用await() happen-before之前的线程中的操作,这些操作是屏障动作的一部分,而这些操作反过来发生在其他线程中相应的await()成功返回后的操作之前

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

      构造方法  
      Constructor 描述
      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 ,并且屏障被置于断开的状态。

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

        结果
        当前线程的到达索引,其中索引 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 ,并且屏障置于断开状态。

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

        参数
        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()