Suppose you have 5 threads out of which 1 is a main thread and other 4 are threads that perform some task.
Now you want the main thread to proceed further only after all the 4 worker threads have finished execution.
Example,
When a laptop is started, many tasks are performed such as initialization of network service, graphic interface, input output drivers, pre-configured startup services etc.
When all these have signaled successful startup, then the login screen is displayed. Consider each of these services as a separate thread and login screen display thread as a thread waiting for these threads to complete.
This thread should proceed only when all the service threads have completed their initialization.

With traditional java thread implementation, you can do this using wait and notifyAll methods. But java also provides a simpler method to accomplish this by using a CountdownLatch.

Read this to know more about java threads.

What is CountDownLatch

CountDownLatch is used to make a thread wait till other threads finish their execution.
When all the threads finish and signal their completion, then the thread which is waiting resumes its execution. CountDownLatch was added in java 1.5.

How to use CountDownLatch in java

A CountDownLatch in java is implemented through a java.util.concurrent.CountDownLatch class. When an object of this class is created, we supply the number of threads for which a thread will wait to finish execution.
This is known as the count of CountDownLatch and it is the value of this count that decides the resumption of waiting thread.
A thread waiting for the execution will resume only when the count becomes 0.

Usage of CountDownLatch is based on below two methods:

await()

When this method is called on an object of CountDownLatch, the current thread pauses execution and goes into waiting state.
The thread keeps on waiting till the count of CountDownLatch becomes zero.
This method should be called inside the thread which needs to wait for the other threads to complete.

countDown()

This method should be called from inside the worker threads. Each time this method is called, the value of count of CountDownLatch reduces by 1.

Thus, the concept of CountDownLatch can be summarized in below steps.

  1. A CountDownLatch is initialized with a count which is the number of child threads for which the main thread will wait before executing further.
    It is an integer.
  2. Thread which starts other threads and which wants to wait for these threads to finish calls await.
  3. Every child thread when finishes execution, calls countDown method.
    This reduces the count by 1.
  4. When all the child threads have completed(and have called countDown), the value of count becomes 0 and main thread resumes its execution.
count of CountDownLatch can also be considered as the number of times for which countDown() method should be invoked on the latch so that the waiting thread can resume.

Remember that both await and countDown should be called on the same object of CountDownLatch. Thus, you need to share the object of CountDownLatch among parent and child threads.

CountDownLatch example

Below is a simple example of a CountDownLatch. It consists of a class Task that implements java.lang.Runnable and represents a task that thread needs to perform.
Task of a thread is written inside the overridden run method of java.lang.Runnable interface.

Learn about overriding methods in java here.

This class also accepts an object of java.util.concurrent.CountDownLatch and calls its countDown method once it finishes.

Task.java

class Task implements Runnable {
 
   CountDownLatch latch;

   /**
    * Constructor
    * @param l
    */
   public Task(CountDownLatch l) {
 this.latch = l;
   }

  @Override
  public void run() {
    try {
      System.out.println("Started: " + Thread.
                                       currentThread().
                                       getName());
      Thread.sleep(2000);
    } catch (InterruptedException e) {
       e.printStackTrace();
    }
    System.out.println("Finished: " + Thread.
                                      currentThread().
                                      getName());
    // reduce count of latch
    latch.countDown();
  }
}

Below is a main class that creates an object of java.util.concurrent.CountDownLatch with a count of 3. It then creates an object of Task class and supplies the same object to three threads that it creates.

After starting all the three threads, it waits for their execution to complete by calling await on the object of CountDownLatch.
This thread will resume execution when all the threads will call countDown() method on the latch.
Note that the object of the CountDownLatch on which it calls await is also shared with all the three threads for which it is waiting.
Each time a thread calls countDown() method, count reduces by 1.
Thus, when all the threads call countDown(), the count reaches 0 and the main thread then continues execution.

MainThread.java

public class MainThread {
 
   public static void main(String[] args) throws 
                                          InterruptedException {
 // create an object of countdownlatch with a count of 3
 CountDownLatch latch = new CountDownLatch(3);
 // create a task
 Task obj = new Task(latch);
 // create three worker threads
 Thread t1 = new Thread(obj);
 Thread t2 = new Thread(obj);
 Thread t3 = new Thread(obj);
 // start threads
 t1.start();
 t2.start();
 t3.start();
 // current thread will wait for the worker threads to complete
 latch.await();
 System.out.println("All Threads completed!!!");
   }
}

Following is the output

Started: Thread-1
Started: Thread-0
Started: Thread-2
Finished: Thread-1
Finished: Thread-2
Finished: Thread-0
All Threads completed!!!

With CountDownLatch in place, the last line will always be printed when all the three threads have finished. Remove the statement latch.await and notice the difference.
Let’s tweak in

  1. count is set when a CountDownLatch is created. Once initialized, count cannot be reset.
  2. The thread in which await is called will keep on waiting infinitely till the count becomes zero.
  3. If the count is greater than the number of threads, then main thread will be stuck forever.
  4. In case you are not sure if a child thread will call countDown using the overloaded await method which takes a timeout value so that the main thread will resume after the specified time and your application will not be stuck forever.
  5. For getting the current count value, call getCount method on the object of CountDownLatch.
  6. Nothing will happen if countDown() method is called and the count is 0.

Leave a Reply