CountDownLatch

CountDownLatch holds a thread to wait until one or more events have occurred. A CountDownLatch is created with the number of events that must occur before the latch is released. Each time an event happens, the count is decremented. When the count reaches zero, the latch opens.

CountDownLatch has the following constructor:

CountDownLatch(int num)
num specifies the number of events that must occur in order for the latch to open.

To wait on the latch, a thread calls await( ), which has the forms shown here:

void await( ) throws InterruptedException
waits until the count associated with the invoking CountDownLatch reaches zero.
void await(long wait, TimeUnit tu) throws InterruptedException
waits only for the period of time specified by wait. The units represented by wait are specified by tu, which is an object the TimeUnit enumeration.

To signal an event, call the countDown( ) method:

void countDown( )
Each call to countDown( ) decrements the count associated with the invoking object.
 
import java.util.concurrent.CountDownLatch;

public class Main implements Runnable {
  CountDownLatch latch;

  Main(CountDownLatch c) {
    latch = c;
    new Thread(this).start();
  }

  public void run() {
    for (int i = 0; i < 5; i++) {
      System.out.println(i);
      latch.countDown(); // decrement count
    }
  }
  public static void main(String args[]) {
    CountDownLatch cdl = new CountDownLatch(5);
    new Main(cdl);
    try {
      cdl.await();
    } catch (Exception exc) {
      System.out.println(exc);
    }
  }
}
  

The following code uses a countdown latch to trigger a coordinated start

 
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
  final static int Count = 3;

  public static void main(String[] args) {
    final CountDownLatch startSignal = new CountDownLatch(1);
    final CountDownLatch doneSignal = new CountDownLatch(Count);
    Runnable r = new Runnable() {
      public void run() {
        try {
          System.out.println(System.currentTimeMillis() + ": " + Thread.currentThread() + ": entered run()");
          startSignal.await(); // wait until told to proceed
          System.out.println(System.currentTimeMillis() + ": " + Thread.currentThread() + ": working");
          Thread.sleep((int) (Math.random() * 1000));
          doneSignal.countDown(); // reduce count on which
          // main thread is waiting
        } catch (InterruptedException ie) {
          System.err.println(ie);
        }
      }
    };
    ExecutorService executor = Executors.newFixedThreadPool(Count);
    for (int i = 0; i < Count; i++){
      executor.execute(r);
    }
      
    try {
      Thread.sleep(1000); // sleep for 1 second
      startSignal.countDown(); // let all threads proceed
      doneSignal.await(); // wait for all threads to finish
      executor.shutdownNow();
    } catch (InterruptedException ie) {
      System.err.println(ie);
    }
  }
}