java.util.concurrent.CyclicBarrier
java.lang.Objectjava.util.concurrent.CyclicBarrier
public class CyclicBarrier extends Object
一个同步辅助类,它允许【一组】线程【互相等待】,直到【到达】某个【公共】屏障点 (common barrier point)。
在涉及一组固定大小的线程的程序中,这些线程必须 【不时地互相等待】,此时 CyclicBarrier 很有用。
因为该 barrier 在释放等待线程后可以重用,所以称它为【循环 的 barrier】。
CyclicBarrier 支持一个可选的 Runnable
命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。
(Barrier :障碍物,屏障;界线)
示例用法:下面是一个在并行分解设计中使用 barrier 的例子:
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(); } }在这个例子中,每个 worker 线程处理矩阵的一行,在处理完所有的行之前,该线程将一直在屏障处等待。处理完所有的行之后,将执行所提供的
Runnable
屏障操作,并合并这些行。如果合并者确定已经找到了一个解决方案,那么
done() 将返回
true,所有的 worker 线程都将终止。
如果屏障操作在执行时不依赖于正挂起的线程,则线程组中的任何线程在获得释放时都能执行该操作。为方便此操作,每次调用 await()
都将返回能到达屏障处的线程的索引。然后,您可以选择哪个线程应该执行屏障操作,例如:
if (barrier.await() == 0) { // log the completion of this iteration }
对于失败的同步尝试,CyclicBarrier 使用了一种要么全部要么全不 (all-or-none) 的破坏模式:如果因为中断、失败或者超时等原因,导致线程过早地离开了屏障点,那么在该屏障点等待的其他所有线程也将通过BrokenBarrierException
(如果它们几乎同时被中断,则用InterruptedException
)以反常的方式离开。
内存一致性效果:线程中调用 await()
之前的操作 happen-before 那些是屏障操作的一部份的操作,后者依次happen-before 紧跟在从另一个线程中对应await()
成功返回的操作。
-
从以下版本开始:
- 1.5 另请参见:
-
CountDownLatch
构造方法摘要 | |
---|---|
CyclicBarrier(int parties) 创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预定义的操作。 | |
CyclicBarrier(int parties,Runnable barrierAction) 创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行。 |
方法摘要 | |
---|---|
int | await() 在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。 |
int | await(long timeout,TimeUnit unit) 在所有参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间。 |
int | getNumberWaiting() 返回当前在屏障处等待的参与者数目。 |
int | getParties() 返回要求启动此 barrier 的参与者数目。 |
boolean | isBroken() 查询此屏障是否处于损坏状态。 |
void | reset() 将屏障重置为其初始状态。 |
构造方法详细信息 |
---|
CyclicBarrier
public CyclicBarrier(int parties, Runnable barrierAction)
-
创建一个新的
CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行。
-
参数:
-
parties
- 在启动 barrier 前必须调用await()
的线程数 -
barrierAction
- 在启动 barrier 时执行的命令;如果不执行任何操作,则该参数为null
抛出:
-
IllegalArgumentException
- 如果parties
小于 1
-
CyclicBarrier
public CyclicBarrier(int parties)
-
创建一个新的
CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预定义的操作。
-
参数:
-
parties
- 在启动 barrier 前必须调用await()
的线程数
抛出:
-
IllegalArgumentException
- 如果parties
小于 1
-
方法详细信息 |
---|
getParties
public int getParties()
- 返回要求启动此 barrier 的参与者数目。
-
-
返回:
- 要求启动此 barrier 的参与者数目
await
public int await() throws InterruptedException, BrokenBarrierException
-
在所有
参与者都已经在此 barrier 上调用
await 方法之前,将一直等待。
如果当前线程不是将到达的最后一个线程,出于调度目的,将禁用它,且在发生以下情况之一前,该线程将一直处于休眠状态:
- 最后一个线程到达;或者
- 其他某个线程中断当前线程;或者
- 其他某个线程中断另一个等待线程;或者
- 其他某个线程在等待 barrier 时超时;或者
- 其他某个线程在此 barrier 上调用
reset()
。
如果当前线程:
- 在进入此方法时已经设置了该线程的中断状态;或者
- 在等待时被中断
InterruptedException
,并且清除当前线程的已中断状态。如果在线程处于等待状态时 barrier 被
reset()
,或者在调用await 时 barrier被损坏,抑或任意一个线程正处于等待状态,则抛出BrokenBarrierException
异常。如果任何线程在等待时被 中断,则其他所有等待线程都将抛出
BrokenBarrierException
异常,并将 barrier 置于损坏状态。如果当前线程是最后一个将要到达的线程,并且构造方法中提供了一个非空的屏障操作,则在允许其他线程继续运行之前,当前线程将运行该操作。如果在执行屏障操作过程中发生异常,则该异常将传播到当前线程中,并将 barrier 置于损坏状态。
-
-
返回:
-
到达的当前线程的索引,其中,索引
getParties()
- 1 指示将到达的第一个线程,零指示最后一个到达的线程
抛出:
-
InterruptedException
- 如果当前线程在等待时被中断 -
BrokenBarrierException
- 如果 另一个 线程在当前线程等待时被中断或超时,或者重置了 barrier,或者在调用await
时 barrier 被损坏,抑或由于异常而导致屏障操作(如果存在)失败。
-
到达的当前线程的索引,其中,索引
await
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
-
在所有
参与者都已经在此屏障上调用
await 方法之前将一直等待,或者超出了指定的等待时间。
如果当前线程不是将到达的最后一个线程,出于调度目的,将禁用它,且在发生以下情况之一前,该线程将一直处于休眠状态:
- 最后一个线程到达;或者
- 超出指定的超时时间;或者
- 其他某个线程中断当前线程;或者
- 其他某个线程中断另一个等待线程;或者
- 其他某个线程在等待 barrier 时超时;或者
- 其他某个线程在此 barrier 上调用
reset()
。
如果当前线程:
- 在进入此方法时已经设置了该线程的中断状态;或者
- 在等待时被中断
InterruptedException
,并且清除当前线程的已中断状态。如果超出指定的等待时间,则抛出
TimeoutException
异常。如果该时间小于等于零,则此方法根本不会等待。如果在线程处于等待状态时 barrier 被
reset()
,或者在调用await 时 barrier被损坏,抑或任意一个线程正处于等待状态,则抛出BrokenBarrierException
异常。如果任何线程在等待时被中断,则其他所有等待线程都将抛出
BrokenBarrierException
,并将屏障置于损坏状态。如果当前线程是最后一个将要到达的线程,并且构造方法中提供了一个非空的屏障操作,则在允许其他线程继续运行之前,当前线程将运行该操作。如果在执行屏障操作过程中发生异常,则该异常将传播到当前线程中,并将 barrier 置于损坏状态。
-
-
参数:
-
timeout
- 等待 barrier 的时间 -
unit
- 超时参数的时间单位
返回:
-
到达的当前线程的索引,其中,索引
getParties()
- 1 指示第一个将要到达的线程,零指示最后一个到达的线程
抛出:
-
InterruptedException
- 如果当前线程在等待时被中断 -
TimeoutException
- 如果超出了指定的超时时间 -
BrokenBarrierException
- 如果 另一个 线程在当前线程等待时被中断或超时,或者重置了 barrier,或者调用await
时 barrier 被损坏,抑或由于异常而导致屏障操作(如果存在)失败。
-
isBroken
public boolean isBroken()
- 查询此屏障是否处于损坏状态。
-
-
返回:
-
如果因为构造或最后一次重置而导致中断或超时,从而使一个或多个参与者摆脱此 barrier,或者因为异常而导致某个屏障操作失败,则返回
true
;否则返回false
。
-
如果因为构造或最后一次重置而导致中断或超时,从而使一个或多个参与者摆脱此 barrier,或者因为异常而导致某个屏障操作失败,则返回
reset
public void reset()
-
将屏障重置为其初始状态。如果所有参与者目前都在屏障处等待,则它们将返回,同时抛出一个
BrokenBarrierException
。注意,在由于其他原因造成损坏 之后,实行重置可能会变得很复杂;此时需要使用其他方式重新同步线程,并选择其中一个线程来执行重置。与为后续使用创建一个新 barrier 相比,这种方法可能更好一些。 -
getNumberWaiting
public int getNumberWaiting()
- 返回当前在屏障处等待的参与者数目。此方法主要用于调试和断言。
-
-
返回:
-
当前阻塞在
await()
中的参与者数目。
-
当前阻塞在