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。カウントがゼロに達する前に待機時間が経過した場合は falseInterruptedException - 待機中に現在のスレッドで割り込みが発生した場合public void countDown()
現在のカウントがゼロより大きい場合、値が減らされます。新しいカウントがゼロの場合、待機中のすべてのスレッドのスケジューリングが再び可能になります。
現在のカウントがゼロの場合、何も行われません。
public long getCount()
通常、このメソッドはデバッグとテストの場合に使用します。
バグまたは機能を送信
詳細な API リファレンスおよび開発者ドキュメントについては、Java SE のドキュメントを参照してください。そのドキュメントには、概念的な概要、用語の定義、回避方法、有効なコード例などの、開発者を対象にしたより詳細な説明が含まれています。
Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.