public class CountDownLatch extends Object
CountDownLatch
は、指定されたカウントで初期化されます。 await
メソッドは、countDown()
メソッドの呼出しによって現在のカウントがゼロに達するまでブロックします。その後、待機中のすべてのスレッドが解放され、以降のawait
のすべての呼出しがただちに復帰します。 これは単発的な現象であり、カウントをリセットすることはできません。 カウントをリセットするバージョンが必要な場合は、CyclicBarrier
の使用を検討してください。
CountDownLatch
はさまざまな目的に使用できる柔軟性の高い同期ツールです。 カウント1で初期化されたCountDownLatch
は、単純なオン/オフのラッチ、つまりゲートとして機能します。await
を呼び出すスレッドはすべて、countDown()
を呼び出すスレッドによって開かれるまでゲートで待機します。 Nに初期化されたCountDownLatch
を使用すると、N個のスレッドが特定のアクションを完了するか、または特定のアクションがN回完了するまで、あるスレッドを待機させることができます。
CountDownLatch
の有効な特性の1つに、countDown
を呼び出すスレッドが、カウントがゼロに達するまで処理を待機する必要がないことです。これは単純に、すべてのスレッドが通過するまで、どのスレッドもawait
を通過できないようにします。
使用例: 次に示すクラスのペアでは、ワーカー・スレッドのグループが次の2つのカウントダウン・ラッチを使用します。
- 最初のクラスは、ドライバの進行準備ができるまで、ワーカーが先に進むのを防ぐ開始信号である。
- 2番目のクラスは、すべてのワーカーが完了するまでドライバの待機を許可する完了信号である。
class Driver { // ...
void main() throws InterruptedException {
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(N);
for (int i = 0; i < N; ++i) // create and start threads
new Thread(new Worker(startSignal, doneSignal)).start();
doSomethingElse(); // don't let run yet
startSignal.countDown(); // let all threads proceed
doSomethingElse();
doneSignal.await(); // wait for all to finish
}
}
class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}
public void run() {
try {
startSignal.await();
doWork();
doneSignal.countDown();
} catch (InterruptedException ex) {} // return;
}
void doWork() { ... }
}
もう1つの標準的な使用法は、問題をN個の部分に分割し、各部を実行してラッチをカウント・ダウンするRunnableを使用して各部分を記述し、すべてのRunnableをexecutorのキューに入れる方法です。 下位部分がすべて完了すると、調整役のスレッドはawaitを抜けることができます。 スレッドがこの方法でカウント・ダウンを繰り返す必要がある場合は、代わりにCyclicBarrier
を使用してください。
class Driver2 { // ...
void main() throws InterruptedException {
CountDownLatch doneSignal = new CountDownLatch(N);
Executor e = ...
for (int i = 0; i < N; ++i) // create and start threads
e.execute(new WorkerRunnable(doneSignal, i));
doneSignal.await(); // wait for all to finish
}
}
class WorkerRunnable implements Runnable {
private final CountDownLatch doneSignal;
private final int i;
WorkerRunnable(CountDownLatch doneSignal, int i) {
this.doneSignal = doneSignal;
this.i = i;
}
public void run() {
try {
doWork(i);
doneSignal.countDown();
} catch (InterruptedException ex) {} // return;
}
void doWork() { ... }
}
メモリー整合性効果: カウントがゼロに達するまで、countDown()
を呼び出す前のスレッド内のアクションは、別のスレッド内の対応するawait()
からの正常な復帰に続くアクションの前に発生します。
- 導入されたバージョン:
- 1.5
-
コンストラクタのサマリー
コンストラクタ コンストラクタ 説明 CountDownLatch(int count)
指定されたカウントで初期化されたCountDownLatch
を構築します。 -
メソッドのサマリー
修飾子と型 メソッド 説明 void
await()
スレッドで割り込みが発生しないかぎり、ラッチのカウント・ダウンがゼロになるまで現在のスレッドを待機させます。boolean
await(long timeout, TimeUnit unit)
スレッドで割り込みが発生するか、指定された待機時間が経過しないかぎり、ラッチのカウント・ダウンがゼロになるまで現在のスレッドを待機させます。void
countDown()
ラッチのカウントを減算し、カウントがゼロに達すると待機中のスレッドをすべて解放します。long
getCount()
現在のカウントを返します。String
toString()
ラッチおよびその状態を識別する文字列を返します。
-
コンストラクタの詳細
-
CountDownLatch
public CountDownLatch(int count)指定されたカウントで初期化されたCountDownLatch
を構築します。- パラメータ:
count
- スレッドがawait()
を通過できるまでにcountDown()
を呼び出す必要のある回数- 例外:
IllegalArgumentException
-count
が負である場合
-
-
メソッドの詳細
-
await
public void await() throws InterruptedExceptionスレッドで割り込みが発生しないかぎり、ラッチのカウント・ダウンがゼロになるまで現在のスレッドを待機させます。現在のカウントがゼロの場合、このメソッドはただちに復帰します。
現在のカウントがゼロより大きい場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の2つのいずれかが起きるまで待機します。
countDown()
メソッドの呼出しにより、カウントがゼロに達する- ほかのスレッドが現在のスレッドに割り込みを行う。
現在のスレッドで、
- このメソッドへのエントリ上で設定された割込みステータスが保持されるか、
- 待機中に割り込みが発生した場合
InterruptedException
がスローされ、現在のスレッドの割込みステータスがクリアされます。- 例外:
InterruptedException
- 待機中に現在のスレッドで割込みが発生した場合
-
await
public boolean await(long timeout, TimeUnit unit) throws InterruptedExceptionスレッドで割り込みが発生するか、指定された待機時間が経過しないかぎり、ラッチのカウント・ダウンがゼロになるまで現在のスレッドを待機させます。現在のカウントがゼロの場合、このメソッドは値
true
でただちに復帰します。現在のカウントがゼロより大きい場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の3つのいずれかが起きるまで待機します。
countDown()
メソッドの呼出しにより、カウントがゼロに達する- ほかのスレッドが現在のスレッドに割り込みを行う。または
- 指定された待機時間が経過する。
カウントがゼロに達した場合、このメソッドは値
true
で復帰します。現在のスレッドで、
- このメソッドへのエントリ上で設定された割込みステータスが保持されるか、
- 待機中に割り込みが発生した場合
InterruptedException
がスローされ、現在のスレッドの割込みステータスがクリアされます。指定された待機時間が経過すると、値
false
が返されます。 時間がゼロまたはそれより小さい場合、メソッドは待機しません。- パラメータ:
timeout
- 待機する最長時間unit
-timeout
引数の時間単位- 戻り値:
- カウントがゼロに達した場合は
true
。カウントがゼロに達する前に待機時間が経過した場合はfalse
- 例外:
InterruptedException
- 待機中に現在のスレッドで割込みが発生した場合
-
countDown
public void countDown()ラッチのカウントを減算し、カウントがゼロに達すると待機中のスレッドをすべて解放します。現在のカウントがゼロより大きい場合、値が減らされます。 新しいカウントがゼロの場合、待機中のすべてのスレッドのスケジューリングが再び可能になります。
現在のカウントがゼロの場合、何も行われません。
-
getCount
public long getCount()現在のカウントを返します。通常、このメソッドはデバッグとテストの場合に使用します。
- 戻り値:
- 現在のカウント
-
toString
public String toString()ラッチおよびその状態を識別する文字列を返します。 状態は括弧で囲まれ、文字列"Count ="
に続いて現在のカウントが含まれます。
-