public class CountDownLatch extends Object
CountDownLatch
は、指定されたカウントで初期化されます。await
メソッドは、countDown()
メソッドの呼出しによって現在のカウントがゼロに達するまでブロックします。その後、待機中のすべてのスレッドが解放され、以降のawait
のすべての呼出しがただちに復帰します。これは単発的な現象であり、カウントをリセットすることはできません。カウントをリセットするバージョンが必要な場合は、CyclicBarrier
の使用を検討してください。
CountDownLatch
はさまざまな目的に使用できる柔軟性の高い同期ツールです。カウント1で初期化されたCountDownLatch
は、単純なオン/オフのラッチ、つまりゲートとして機能します。await
を呼び出すスレッドはすべて、countDown()
を呼び出すスレッドによって開かれるまでゲートで待機します。Nに初期化されたCountDownLatch
を使用すると、N個のスレッドが特定のアクションを完了するか、または特定のアクションがN回完了するまで、あるスレッドを待機させることができます。
CountDownLatch
の有効な特性の1つに、countDown
を呼び出すスレッドが、カウントがゼロに達するまで処理を待機する必要がないことです。これは単純に、すべてのスレッドが通過するまで、どのスレッドもawait
を通過できないようにします。
使用例: 次に示すクラスのペアでは、ワーカー・スレッドのグループが次の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()
からの正常な復帰に続くアクションの前に発生します。
コンストラクタと説明 |
---|
CountDownLatch(int count)
指定されたカウントで初期化された
CountDownLatch を構築します。 |
修飾子と型 | メソッドと説明 |
---|---|
void |
await()
スレッドで割り込みが発生しないかぎり、ラッチのカウント・ダウンがゼロになるまで現在のスレッドを待機させます。
|
boolean |
await(long timeout, TimeUnit unit)
スレッドで割り込みが発生するか、指定された待機時間が経過しないかぎり、ラッチのカウント・ダウンがゼロになるまで現在のスレッドを待機させます。
|
void |
countDown()
ラッチのカウントを減算し、カウントがゼロに達すると待機中のスレッドをすべて解放します。
|
long |
getCount()
現在のカウントを返します。
|
String |
toString()
ラッチおよびその状態を識別する文字列を返します。
|
public CountDownLatch(int count)
CountDownLatch
を構築します。count
- スレッドがawait()
を通過できるまでにcountDown()
を呼び出す必要のある回数IllegalArgumentException
- count
が負である場合public void await() throws InterruptedException
現在のカウントがゼロの場合、このメソッドはただちに復帰します。
現在のカウントがゼロより大きい場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の2つのいずれかが起きるまで待機します。
countDown()
メソッドの呼出しにより、カウントがゼロに達する
現在のスレッドで、
InterruptedException
がスローされ、現在のスレッドの割込みステータスがクリアされます。InterruptedException
- 待機中に現在のスレッドで割込みが発生した場合public boolean await(long timeout, TimeUnit unit) throws InterruptedException
現在のカウントがゼロの場合、このメソッドは値true
でただちに復帰します。
現在のカウントがゼロより大きい場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の3つのいずれかが起きるまで待機します。
countDown()
メソッドの呼出しにより、カウントがゼロに達する
カウントがゼロに達した場合、このメソッドは値true
で復帰します。
現在のスレッドで、
InterruptedException
がスローされ、現在のスレッドの割込みステータスがクリアされます。
指定された待機時間が経過すると、値false
が返されます。時間がゼロまたはそれより小さい場合、メソッドは待機しません。
timeout
- 待機する最長時間unit
- timeout
引数の時間単位true
。カウントがゼロに達する前に待機時間が経過した場合はfalse
InterruptedException
- 待機中に現在のスレッドで割込みが発生した場合public void countDown()
現在のカウントがゼロより大きい場合、値が減らされます。新しいカウントがゼロの場合、待機中のすべてのスレッドのスケジューリングが再び可能になります。
現在のカウントがゼロの場合、何も行われません。
public long getCount()
通常、このメソッドはデバッグとテストの場合に使用します。
バグまたは機能を送信
詳細なAPIリファレンスおよび開発者ドキュメントについては、Java SEのドキュメントを参照してください。そのドキュメントには、概念的な概要、用語の定義、回避方法、有効なコード例などの、開発者を対象にしたより詳細な説明が含まれています。
Copyright© 1993, 2014, Oracle and/or its affiliates. All rights reserved.