CyclicBarrier
は、オプションのRunnable
コマンドをサポートします。これは、パーティ内の最後のスレッドが到着した後で、スレッドが解放される前にバリアー・ポイントごとに1回実行されます。 このバリアー・アクションは、いずれかのパーティが処理を続行する前に共有状態を更新するために役立ちます。
使用例: 次に、並列分解設計でのバリアーの使用例を示します。
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()
を呼び出す前のスレッド内のアクションは、バリアー・アクションの一部であるアクションよりも前に発生し、一方それは、ほかのスレッド内の対応するawait()
からの正常な復帰に続くアクションよりも前に発生します。
- 導入されたバージョン:
- 1.5
- 関連項目:
CountDownLatch
,Phaser
-
コンストラクタのサマリー
コンストラクタ説明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すべてのパーティがこのバリアーでawait
を呼び出すまで待機します。現在のスレッドが、到着する最後のスレッドではない場合、スレッドのスケジューリングに関して無効になり、次のいずれかが起きるまで待機します。
- 最後のスレッドが到着する
- ほかのスレッドが現在のスレッドに割り込みを行う。または
- 別のスレッドが待機中の他のスレッドの1つに割り込みを行う
- バリアーの待機中にほかのスレッドがタイム・アウトする
- ほかのスレッドがこのバリアーに対して
reset()
を呼び出す。
現在のスレッドで、
- このメソッドへのエントリ上で設定された割込みステータスが保持されるか、
- 待機中に割り込みが発生した場合
InterruptedException
がスローされ、現在のスレッドの割込みステータスがクリアされます。いずれかのスレッドが待機中にバリアーで
reset()
が実行されるか、awaitの呼出し時、またはいずれかのスレッドが待機中にバリアーが破壊された
場合、BrokenBarrierException
がスローされます。待機中のいずれかのスレッドで割り込みが発生した場合、待機中の他のスレッドがすべて
BrokenBarrierException
をスローし、バリアーが故障状態に置かれます。現在のスレッドが到着する最後のスレッドであり、コンストラクタ内でnullではないバリアー・アクションが指定される場合、現在のスレッドはアクションを実行してから、ほかのスレッドの続行を許可します。 バリアー・アクション中に例外が発生すると、現在のスレッド内にその例外が伝えられ、バリアーが故障状態に置かれます。
- 戻り値:
- 現在のスレッドの到着インデックス。インデックス
getParties() - 1
は最初に到着するスレッドを、ゼロは最後に到着するスレッドを示す - 例外:
InterruptedException
- 待機中に現在のスレッドで割込みが発生した場合BrokenBarrierException
- 現在のスレッドの待機中に別のスレッドで割込みが発生したかタイム・アウトした場合、バリアーがリセットされた場合、await
が呼び出されたときにバリアーが破壊された場合、または例外のためにバリアー・アクション(存在する場合)が失敗した場合
-
await
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutExceptionすべてのパーティがこのバリアーでawait
を呼び出すか、指定された待機時間が経過するまで待機します。現在のスレッドが、到着する最後のスレッドではない場合、スレッドのスケジューリングに関して無効になり、次のいずれかが起きるまで待機します。
- 最後のスレッドが到着する
- 指定されたタイム・アウトが経過する
- ほかのスレッドが現在のスレッドに割り込みを行う。または
- 別のスレッドが待機中の他のスレッドの1つに割り込みを行う
- バリアーの待機中にほかのスレッドがタイム・アウトする
- ほかのスレッドがこのバリアーに対して
reset()
を呼び出す。
現在のスレッドで、
- このメソッドへのエントリ上で設定された割込みステータスが保持されるか、
- 待機中に割り込みが発生した場合
InterruptedException
がスローされ、現在のスレッドの割込みステータスがクリアされます。指定された待機時間が経過すると、
TimeoutException
がスローされます。 時間がゼロまたはそれより小さい場合、メソッドは待機しません。いずれかのスレッドが待機中にバリアーで
reset()
が実行されるか、awaitの呼出し時、またはいずれかのスレッドが待機中にバリアーが破壊された
場合、BrokenBarrierException
がスローされます。待機中のいずれかのスレッドで割り込みが発生した場合、待機中の他のスレッドがすべて
BrokenBarrierException
をスローし、バリアーが故障状態に置かれます。現在のスレッドが到着する最後のスレッドであり、コンストラクタ内でnullではないバリアー・アクションが指定される場合、現在のスレッドはアクションを実行してから、ほかのスレッドの続行を許可します。 バリアー・アクション中に例外が発生すると、現在のスレッド内にその例外が伝えられ、バリアーが故障状態に置かれます。
- パラメータ:
timeout
- バリアーを待機する時間unit
- タイムアウト・パラメータの時間単位- 戻り値:
- 現在のスレッドの到着インデックス。インデックス
getParties() - 1
は最初に到着するスレッドを、ゼロは最後に到着するスレッドを示す - 例外:
InterruptedException
- 待機中に現在のスレッドで割込みが発生した場合TimeoutException
- 指定されたタイム・アウトが経過した場合。 この場合はバリアーが破壊されます。BrokenBarrierException
- 現在のスレッドの待機中に別のスレッドで割込みが発生したかタイム・アウトした場合、バリアーがリセットされた場合、await
が呼び出されたときにバリアーが破壊された場合、または例外のためにバリアー・アクション(存在する場合)が失敗した場合
-
isBroken
public boolean isBroken()このバリアーが故障状態にあるかどうかを問い合わせます。- 戻り値:
- バリアーの構築または最後のリセット以降に割り込みまたはタイム・アウトのために1つ以上のパーティがこのバリアーを破壊したか、または例外のためにバリアー・アクションが失敗した場合は
true
。それ以外の場合はfalse
。
-
reset
public void reset()バリアーを初期状態にリセットします。 いずれかのパーティが現在バリアーで待機している場合、それらのパーティはBrokenBarrierException
で復帰します。 ほかの理由で切断が発生したあとにリセットする場合は、実行が複雑になる場合があることに注意してください。つまり、ほかの何らかの方法でスレッドを再同期し、リセットを実行するスレッドを選択する必要があります。 こうした状況では、以降で使用するためにバリアーを新規作成するほうが望ましい場合があります。 -
getNumberWaiting
public int getNumberWaiting()バリアーで現在待機しているパーティの数を返します。 このメソッドは、主にデバッグとアサーションで役立ちます。- 戻り値:
await()
で現在ブロックされているパーティの数
-