Java CountDownLatch with Example

As per java docs, CountDownLatch is a synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. CountDownLatch concept is very common interview question in java concurrency, so make sure you understand it well. In this post, I will cover following points related to CountDownLatch in java concurrency.

1. CountDownLatch class

CountDownLatch was introduced with JDK 1.5 along with other concurrent utilities like CyclicBarrier, Semaphore, ConcurrentHashMap and BlockingQueue in java.util.concurrent package. This class enables a Java thread to wait until the other set of threads completes their tasks.

For example, the application’s main thread wants to wait, till other service threads which are responsible for starting framework services have completed their tasks.

CountDownLatch works by having a counter initialized with a number of threads, which is decremented each time a thread completes its execution. When the count reaches zero, it means all threads have completed their execution, and the main thread waiting on the latch resumes the execution.

CountdownLatch
CountDownLatch Concept

Pseudo code for CountDownLatch can be written like this:

- Main thread start
- Create CountDownLatch for N threads
- Create and start N threads
- Main thread wait on latch
     - N threads completes their tasks and count down the latch
- Main thread resume execution

2. How does a CountDownLatch work?

CountDownLatch class defines one constructor inside:

//Constructs a CountDownLatch initialized with the given count.
public CountDownLatch(int count) {...}

This count is essentially the number of threads, for which the latch should wait. This value can be set only once, and it provides no other mechanism to reset this count.

  • The first interaction with CountDownLatch is in main thread which is going to wait for other threads. This main thread must call, CountDownLatch.await() method immediately after starting other threads.
  • The execution will stop on latch.await() method till the time, other threads complete their execution.
  • Note that these N threads must have a reference to the latch object because they will need to notify the latch object that they have completed their task. This notification is done by CountDownLatch.countDown().
  • Each invocation of countDown() decreases the initial count set in the constructor, by 1. So, when all N threads have called this method, the count reaches to zero, and the main thread is allowed to resume its execution past await() method.

3. CountDownLatch Example

In this example, I have simulated an application startup class that starts N threads that will check for external systems and report back to latch, on which startup class is waiting. As soon as all services are verified and checked startup proceeds.

BaseHealthChecker – This class is a Runnable and parent for all specific external service health checkers. This remove the code duplicacy and central control over the latch.

public abstract class BaseHealthChecker implements Runnable {
   
  private CountDownLatch _latch;
  private String _serviceName;
  private boolean _serviceUp;
   
  //Get latch object in constructor so that after completing the task, thread can countDown() the latch
  public BaseHealthChecker(String serviceName, CountDownLatch latch)
  {
    super();
    this._latch = latch;
    this._serviceName = serviceName;
    this._serviceUp = false;
  }
 
  @Override
  public void run() {
    try {
      verifyService();
      _serviceUp = true;
    } catch (Throwable t) {
      t.printStackTrace(System.err);
      _serviceUp = false;
    } finally {
      if(_latch != null) {
        _latch.countDown();
      }
    }
  }
 
  public String getServiceName() {
    return _serviceName;
  }
 
  public boolean isServiceUp() {
    return _serviceUp;
  }
  //This methos needs to be implemented by all specific service checker
  public abstract void verifyService();
}

NetworkHealthChecker: This class extends BaseHealthChecker and needs to provide an implementation of verifyService() method. Similarly, DatabaseHealthChecker and CacheHealthChecker are same as NetworkHealthChecker apart from their service names and sleep time.

public class NetworkHealthChecker extends BaseHealthChecker
{
  public NetworkHealthChecker (CountDownLatch latch)  {
    super("Network Service", latch);
  }
   
  @Override
  public void verifyService() 
  {
    System.out.println("Checking " + this.getServiceName());
    try
    {
      Thread.sleep(7000);
    } 
    catch (InterruptedException e)
    {
      e.printStackTrace();
    }
    System.out.println(this.getServiceName() + " is UP");
  }
}

ApplicationStartupUtil: This class is the main startup class that initializes the latch and waits for this latch till all services are checked.

public class ApplicationStartupUtil 
{
  //List of service checkers
  private static List<BaseHealthChecker> _services;
   
  //This latch will be used to wait on
  private static CountDownLatch _latch;
   
  private ApplicationStartupUtil()
  {
  }
   
  private final static ApplicationStartupUtil INSTANCE = new ApplicationStartupUtil();
   
  public static ApplicationStartupUtil getInstance()
  {
    return INSTANCE;
  }
   
  public static boolean checkExternalServices() throws Exception
  {
    //Initialize the latch with number of service checkers
    _latch = new CountDownLatch(3);
     
    //All add checker in lists
    _services = new ArrayList<BaseHealthChecker>();
    _services.add(new NetworkHealthChecker(_latch));
    _services.add(new CacheHealthChecker(_latch));
    _services.add(new DatabaseHealthChecker(_latch));
     
    //Start service checkers using executor framework
    Executor executor = Executors.newFixedThreadPool(_services.size());
     
    for(final BaseHealthChecker v : _services) 
    {
      executor.execute(v);
    }
     
    //Now wait till all services are checked
    _latch.await();
     
    //Services are file and now proceed startup
    for(final BaseHealthChecker v : _services) 
    {
      if( ! v.isServiceUp())
      {
        return false;
      }
    }
    return true;
  }
}

Now you can write any test class to check the functionality of the latch.

public class Main {
  public static void main(String[] args) 
  {
    boolean result = false;
    try {
      result = ApplicationStartupUtil.checkExternalServices();
    } catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println("External services validation completed !! Result was :: "+ result);
  }
}

Program output is:

Checking Network Service
Checking Cache Service
Checking Database Service
Database Service is UP
Cache Service is UP
Network Service is UP
External services validation completed !! Result was :: true

4. Possible Usages of CountDownLatch

Let’s try to identify some possible usage of CountDownLatch in real-life java applications. I am listing, as much I can recall. If you have any other possible usage, please leave a comment. It will help others.

  1. Achieving maximum parallelism: Sometimes we want to start a number of threads at the same time to achieve maximum parallelism. For example, we want to test a class for being a singleton. This can be done easily if we create a latch with initial count 1, and make wait all threads wait for the latch. A single call to countDown() method will resume execution for all waiting threads at the same time.
  2. Wait for N threads to complete before resuming execution: For example, an application start-up class wants to ensure that all N external systems are UP and running before handling the user requests.
  3. Deadlock detection: A very handy use case in which you can use N threads to access a shared resource with a different number of threads in each test phase, and try to create a deadlock.

5. Conclusion

In this tutorial, we learned the basics of CountDownLatch and how to use it in real-life applications. We learned important methods and how to use them to control the flow the application.

Happy Learning !!

Comments

Subscribe
Notify of
guest
31 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode