CountDownLatch allows one or more threads to wait until a set of operations being performed in other threads completes. It is a synchronization aid.

General behavior is as follows:

A CountDownLatch is initialized with a given count. The await methods block until the current count reaches zero due to invocations of the countDown method, after which all waiting threads are released and any subsequent invocations of await return immediately.

Let’s say, you have 5 worker threads. And you have following requirements:

  • All threads should start at the same time
  • Some operation should be performed after all threads are finished.

To achieve this we will create 2 CountDownLatch instances in the main thread, pass these latches to worker threads. Start signal is a CountDownLatch with an initial value of 1. Done signal is a CountDownLatch with an initial value of 5 which is the number of worker threads.

public class CountDownLatchTest {

    public static void main(String[] args) throws InterruptedException {
        countDownLatch();
    }

    public static void countDownLatch() throws InterruptedException {
        final int executionCount = 5;
        final CountDownLatch startSignal = new CountDownLatch(1);
        final CountDownLatch doneSignal = new CountDownLatch(executionCount);
        final ExecutorService threadPool = Executors.newFixedThreadPool(5);

        for (int i = 0; i < executionCount; ++i) {
            threadPool.execute(new Worker(startSignal, doneSignal));
        }

        startSignal.countDown();      // Let all threads proceed
        doneSignal.await();           // Wait for all to finish
        System.out.println("All done. Performing some operation!");
        threadPool.shutdown();
        threadPool.awaitTermination(10, TimeUnit.SECONDS);
    }

    static 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();
                System.out.println("Done");
                doneSignal.countDown();
            } catch (InterruptedException ex) {
                System.out.println("Error");
            }
        }

        void doWork() {
            System.out.println("Doing work");
        }
    }
}

 

Leave a Reply

Close Menu