JUC

CyclicBarrier | 译

2022-11-02  本文已影响0人  zlzl_

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html

Class CyclicBarrier

java.util.concurrent.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;
     barrier = new CyclicBarrier(N,
                                 new Runnable() {
                                   public void run() {
                                     mergeRows(...);
                                   }
                                 });
     for (int i = 0; i < N; ++i)
       new Thread(new Worker(i)).start();

     waitUntilDone();
   }
 }

在这里,每个工作线程处理矩阵的一行,然后在屏障处等待,直到处理完所有行。 处理完所有行后,将执行提供的 Runnable 屏障操作并合并行。 如果合并确定已找到解决方案,则 done() 将返回 true 并且每个工作人员将终止。
如果屏障动作在执行时不依赖于被挂起的各方,那么该方中的任何线程都可以在它被释放时执行该动作。 为了促进这一点,每次调用 await() 都会返回该线程在屏障处的到达索引。 然后,您可以选择哪个线程应该执行屏障操作,例如:

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

CyclicBarrier 对失败的同步尝试使用全有或全无中断模型:如果线程由于中断、故障或超时而过早离开屏障点,则在该屏障点等待的所有其他线程也会通过 BrokenBarrierException(或 InterruptedException 如果他们也几乎同时被打断)。

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

Constructor Detail

public CyclicBarrier(int parties, Runnable barrierAction)

创建一个新的 CyclicBarrier,当给定数量的参与方(线程)正在等待它时,它将触发,并且当障碍被触发时,它将执行给定的屏障动作,由最后一个进入屏障的线程执行。

public CyclicBarrier(int parties)

创建一个新的 CyclicBarrier,它将在给定数量的参与方(线程)等待它时触发,并且在触发障碍时不执行预定义的操作。

public int getParties()

返回触发此障碍所需的参与方数量。

public int await() throws InterruptedException, BrokenBarrierException

等到所有各方都在此屏障上调用了 await。
如果当前线程不是最后到达的,则出于线程调度目的将其禁用并处于休眠状态,直到发生以下情况之一:

如果任何线程在等待时被中断,那么所有其他等待的线程都会抛出 BrokenBarrierException 并且屏障处于损坏状态。

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

public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException

等待,直到所有各方都在此屏障上调用了 await,或者指定的等待时间过去。
如果当前线程不是最后到达的,则出于线程调度目的将其禁用并处于休眠状态,直到发生以下情况之一:

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

如果任何线程在等待时被中断,那么所有其他等待的线程都会抛出 BrokenBarrierException 并且屏障处于损坏状态。

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

public boolean isBroken()

查询此屏障是否处于损坏状态。

public void reset()

将屏障重置为其初始状态。 如果任何一方当前在屏障处等待,他们将返回一个 BrokenBarrierException。 请注意,由于其他原因发生破损后的重置可能会很复杂; 线程需要以其他方式重新同步,并选择一个执行重置。 相反,最好为后续使用创建一个新的屏障。

public int getNumberWaiting()

返回当前在屏障处等待的参与方数量。 此方法主要用于调试和断言。

上一篇下一篇

猜你喜欢

热点阅读