CountDownLatch is utility under java.util.concurrent package.

We initialise CountDownLatch with some integer count value. One or more threads will wait for count value to be '0'. As we pass any checkpoint in execution, we will call countDown() method and decrease count by one. Waiting threads will continue execution when this count becomes 0.



Use Case


Where one or more threads are waiting for a particular sequence to execute. After that waiting threads will execute.

Example


Taking example that can be easiest to remember. Let's say you are starting your computer and waiting for login screen to appear. Now in background computer is completing checks which must pass for computer to function. Some of these checks are Disk, Network, Keyboard, Mouse...etc

There are other checks as well but i am taking above four checks in this example. So if these checks are passed in background by a manager thread then

woo...computer will work and you will be able to see login screen.

In example below :-

LoginWait class is for Login Job(task). Thread executing this job will await for pre-checks to complete
StartupTaskCheck class is for checking all required resources for computer to work and Login to appear.
CountDownLatchExample class is manager which is creating threads and executing above mentioned jobs.

LoginWait thread will start and wait for pre-checks to complete, countdown to become '0' . Every-time a pre-check is passed, it will call countDown() method to decrease the count by one.

When all checks are passes, count will become 0, allowing LoginWait thread to continue. Now let's run example below and see results.



package com.techiekunal.examples;

import java.util.concurrent.CountDownLatch;

/**
 * Let's implement CountDownLatch for system login
 * Assuming that it requires keyboard, mouse, disk, network threads to be reach at active stage
 * Only then computer will start and ask for login
 * 
 * @author Kunal.Saxena
 *
 */

// Login Job
class LoginWait implements Runnable {

 final CountDownLatch countDownLatch;
 
 public LoginWait(CountDownLatch countDownLatch) {
  this.countDownLatch = countDownLatch;
 }
 
 @Override
 public void run() {
  try {
   System.out.println("Thread " + Thread.currentThread().getName() + " will wait for all system check to pass");
   countDownLatch.await();
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("");
  System.out.println("Login pre-check passed. Now you can Login.");
 }
 
}

// Class to check Login pre-cheks
class StartupTaskCheck implements Runnable {

 final CountDownLatch countDownLatch;
 
 public StartupTaskCheck(CountDownLatch countDownLatch) {
  this.countDownLatch = countDownLatch;
 }
 
 @Override
 public void run() {
  try {
   System.out.println("Disk Ready.");
   Thread.sleep(1000);
   countDownLatch.countDown();
   
   System.out.println("Network Ready.");
   Thread.sleep(1000);
   countDownLatch.countDown();
   
   System.out.println("Keyboard Ready.");
   Thread.sleep(1000);
   countDownLatch.countDown();
   
   System.out.println("Mouse Ready.");
   Thread.sleep(1000);
   countDownLatch.countDown();
   
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }
 
}

// Manager Thread
public class CountDownLatchExample {

 public static void main(String[] args) {
  
  CountDownLatch countDownLatch = new CountDownLatch(4);
  
  StartupTaskCheck check = new StartupTaskCheck(countDownLatch);
  LoginWait wait = new LoginWait(countDownLatch);
  
  new Thread(check,"Sys Check Thread").start();
  new Thread(wait,"Login Thread").start();
 }
 
}

Output


Disk Ready. 
Thread Login Thread will wait for all system check to pass 
Network Ready. 
Keyboard Ready. 
Mouse Ready. 
Login pre-check passed. Now you can Login.


I hope this CountDownLatch example is easy to understand and remember.

What will happen if one of the pre-check failed or catch exception and exit. Will countdown latch re-execute sequence? Are there other options? What to do?

We will see this in next Article. :-)