Java CountDownLatch Example

CountDowaLatch is a high-level synchronization utility which is used to prevent a particular thread to start processing until all threads are ready. This is achieved by a countdown. The thread, which needs to wait for starts with a counter, each thread them make the count down by 1 when they become ready, once the last thread call countDown() method, then the latch is broken and the thread waiting with counter starts running. CountDownLatch is a useful synchronizer and used heavily in multi-threaded testing. You can use this class to simulate truly concurrent behavior i.e. trying to access something at the same time once every thread is ready. Worth noting is that CountDownLatch starts with a fixed number of counts which cannot be changed later, though this restriction is re-mediated in Java 7 by introducing a similar but flexible concurrency utility called Phaser.

There is another similar utility called CyclicBarrier, which can also be used in this situation, where one thread needs to wait for other threads before they start processing. Only difference between CyclicBarrier and CountDownLatch is that you can reuse the barrier even after its broker but you cannot reuse the count down latch, once count reaches to zero.

Mastering Concurrency is not easy but if you seriously wants to become an expert Java programmer, you got to tame this horse. One thing which can help you in your journey is the Brian Goetz classic, Java Concurrency in Practice. One of the most recommended book for Java programmer.





How to use CountDownLatch in Java?

Theory is easy to read but you cannot understand it until you see it live in action, this is even more true with concurrency and multi-threading. So let's see how to use CountDownLatch in Java with a simple demo. In this example, we have a main thread which is required to wait until all worker thread finished their task. In order to achieve this, I have created a CountDownLatch with number of count equal to 4, which is the total number of worker threads. I then passed this CountDownLatch to each worker thread, whenever they complete their task, they call countDown() method, once last worker thread calls the countDown() method then the latch is broken and main thread which has been waiting on latch start running again and finished its execution.

CountDownLatch Example in Java


In order to truly understand this problem, you first need to run by by commenting latch.await() call in main method, without this call main thread will not for any worker thread to finish their execution and it will terminate as soon as possible, may be even before any worker thread get started. If you run again by un-commenting latch.await() then you will always see that main thread has finished last. Why? because await() is a blocking call and it blocks until count reaches zero.

Also, you cannot reuse the latch once count=0, calling await() method on latch will have no effect i.e. thread will not block, but they not throw any exception as well, which is little bit of counter intuitive if you are expecting an IllegalThreadStateException.

You can also check Core Java Volume 1 - Fundamentals by Cay S. Horstmann to learn more about these higher level concurrency utilities introduced on Java 1.5 release.

How to use CountDownLatch in Java


Here is the complete program and code to use CountDownLatch in Java :

import java.util.concurrent.CountDownLatch;

/**
 * Java Program to demonstrate how to use CountDownLatch, Its used when a thread
 * needs to wait for other threads before starting its work.
 * 
 * @author Javin Paul
 */
public class CountDownLatchDemo {

    public static void main(String args[]) throws InterruptedException {
        
        CountDownLatch latch = new CountDownLatch(4);
        Worker first = new Worker(1000, latch, "WORKER-1");
        Worker second = new Worker(2000, latch, "WORKER-2");
        Worker third = new Worker(3000, latch, "WORKER-3");
        Worker fourth = new Worker(4000, latch, "WORKER-4");
        
        first.start();
        second.start();
        third.start();
        fourth.start();
        
        // Main thread will wait until all thread finished
        latch.await();
        
        System.out.println(Thread.currentThread().getName() + " has finished");

    }

}

class Worker extends Thread {
    private int delay;
    private CountDownLatch latch;

    public Worker(int delay, CountDownLatch latch, String name) {
        super(name);
        this.delay = delay;
        this.latch = latch;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(delay);
            latch.countDown();
            System.out.println(Thread.currentThread().getName() + " has finished");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Output
WORKER-1 has finished
WORKER-2 has finished
WORKER-3 has finished
WORKER-4 has finished
main has finished

If you call latch.await() again, after count reaches to zero, it will not stop the main thread again, neither it will throw any Exception, it will just pass through it, as shown below :

// Main thread will wait until all thread finished
latch.await();
        
System.out.println(Thread.currentThread().getName() + " has started running again");
        
latch.await();
System.out.println(Thread.currentThread().getName() + " has finished");

Output
main has started running again
main has finished

This is where CountDownLatch is different than CyclicBarrier because you can reuse the barrier to stop the thread even after barrier is broken.



Important points about CountDownLatch in Java

Let's revisit some important things about CountDownLatch in Java. This will help you to retain the knowledge you have just learned :

1) When you create an object of CountDownLatch you pass an int to its constructor (the count), this is actually number of invited parties (threads) for an event.

2) The thread, which is dependent on other threads to start processing, waits on latch until every other thread has called count down. All threads, which are waiting on await() proceed together once count down reaches to zero.

3) countDown() method decrements the count and await() method blocks until count == 0

4) Once count reaches to zero, countdown latch cannot be used again, calling await() method on that latch will not stop any thread, but it will neither throw any exception.

5) One of the popular use of CountDownLatch is in testing concurrent code, by using this latch you can guarantee that multiple threads are firing request simultaneously or executing code at almost same time.

6) There is a similar concurrency utility called CyclicBarrier, which can also use to simulate this scenario but difference between CountDownLatch and CyclicBarrier is that you can reuse the cyclic barrier once the barrier is broken but you cannot reuse the CountDownLatch one count reaches to zero.

7) Java 7 also introduced a flexible alternative of CountDownLatch, known as Phaser. It also has number of unarrived party just like barrier and latch but that number is flexible. So its more like you will not block if one of the guest bunks the party.


That's all in this Java CountDownLatch example. In this tutorial, you have learned how to use CountDownLatch in Java to make sure your key thread starts processing once all pre-conditions are full-filled or when all threads are ready. There are two other similar utility, one is called Phaser and other is called CyclicBarrier, if you want a dynamic count, go for Phaser and if you want to reuse the barrier again and again, go for CyclicBarrier. We will see examples of this two synchronizers in Java in our next Java Concurrency tutorial.

Recommended resources for further learning :
  • Java documentation of CountDownLatch (documentation)
  • Java Concurrency in Practice by Brian Goetz (the book)
  • The Art of Multiprocessor Programming by Maurice Herlihy  (the book)


1 comment:

  1. Here you can find my article where in the example code you can see use of CountDownLatch to wait for specific websocket messages. Maybe someone will find it useful.
    http://blog.mwrobel.eu/activiti-bpmn-engine-events-via-websockets/?lang=en

    ReplyDelete