モジュール java.base
パッケージ java.util.concurrent

クラスCountDownLatch

java.lang.Object
java.util.concurrent.CountDownLatch

public class CountDownLatch extends Object
ほかのスレッドで実行中の操作セットが完了するまで、1つ以上のスレッドを待機可能にする同期化支援機能です。

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() {
     doWork();
     doneSignal.countDown();
   }

   void doWork() { ... }
 }

メモリー整合性効果: カウントがゼロに達するまで、countDown()を呼び出す前のスレッド内のアクションは、別のスレッド内の対応するawait()からの正常な復帰に続くアクションの前に発生します。

導入されたバージョン:
1.5
  • コンストラクタのサマリー

    コンストラクタ
    コンストラクタ
    説明
    CountDownLatch(int count)
    指定されたカウントで初期化されたCountDownLatchを構築します。
  • メソッドのサマリー

    修飾子と型
    メソッド
    説明
    void
    スレッドで割り込みが発生しないかぎり、ラッチのカウント・ダウンがゼロになるまで現在のスレッドを待機させます。
    boolean
    await(long timeout, TimeUnit unit)
    スレッドで割り込みが発生するか、指定された待機時間が経過しないかぎり、ラッチのカウント・ダウンがゼロになるまで現在のスレッドを待機させます。
    void
    ラッチのカウントを減算し、カウントがゼロに達すると待機中のスレッドをすべて解放します。
    long
    現在のカウントを返します。
    ラッチおよびその状態を識別する文字列を返します。

    クラス java.lang.Objectで宣言されたメソッド

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
  • コンストラクタの詳細

    • 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 ="に続いて現在のカウントが含まれます。
      オーバーライド:
      toString、クラスObject
      戻り値:
      このラッチおよびその状態を識別する文字列