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。
如果当前线程不是最后到达的,则出于线程调度目的将其禁用并处于休眠状态,直到发生以下情况之一:
- 最后一个线程到达;或者
- 其他一些线程中断当前线程;或者
- 其他一些线程中断了其他等待线程之一;或者
- 其他一些线程在等待屏障时超时;或者
- 其他一些线程在此屏障上调用 reset()。
如果当前线程: - 在进入此方法时设置其中断状态;或者
- 等待时被打断
然后抛出 InterruptedException 并清除当前线程的中断状态。
如果在任何线程等待时屏障被 reset(),或者在调用 await 时屏障被破坏,或者在任何线程正在等待时,则抛出 BrokenBarrierException。
如果任何线程在等待时被中断,那么所有其他等待的线程都会抛出 BrokenBarrierException 并且屏障处于损坏状态。
如果当前线程是最后到达的线程,并且在构造函数中提供了非空屏障操作,则当前线程在允许其他线程继续之前运行该操作。如果在屏障操作期间发生异常,则该异常将在当前线程中传播,并且屏障处于损坏状态。
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
等待,直到所有各方都在此屏障上调用了 await,或者指定的等待时间过去。
如果当前线程不是最后到达的,则出于线程调度目的将其禁用并处于休眠状态,直到发生以下情况之一:
-
最后一个线程到达;或者
-
指定的超时时间过去;或者
-
其他一些线程中断当前线程;或者
-
其他一些线程中断了其他等待线程之一;或者
-
其他一些线程在等待屏障时超时;或者
-
其他一些线程在此屏障上调用 reset()。
如果当前线程: -
在进入此方法时设置其中断状态;或者
-
等待时被打断
然后抛出 InterruptedException 并清除当前线程的中断状态。
如果指定的等待时间过去,则抛出 TimeoutException。如果时间小于或等于零,则该方法根本不会等待。
如果在任何线程等待时屏障被 reset(),或者在调用 await 时屏障被破坏,或者在任何线程正在等待时,则抛出 BrokenBarrierException。
如果任何线程在等待时被中断,那么所有其他等待的线程都会抛出 BrokenBarrierException 并且屏障处于损坏状态。
如果当前线程是最后到达的线程,并且在构造函数中提供了非空屏障操作,则当前线程在允许其他线程继续之前运行该操作。如果在屏障操作期间发生异常,则该异常将在当前线程中传播,并且屏障处于损坏状态。
public boolean isBroken()
查询此屏障是否处于损坏状态。
public void reset()
将屏障重置为其初始状态。 如果任何一方当前在屏障处等待,他们将返回一个 BrokenBarrierException。 请注意,由于其他原因发生破损后的重置可能会很复杂; 线程需要以其他方式重新同步,并选择一个执行重置。 相反,最好为后续使用创建一个新的屏障。
public int getNumberWaiting()
返回当前在屏障处等待的参与方数量。 此方法主要用于调试和断言。
网友评论