Sunday, 29 April 2018

Java CountDownLatch Example - Multithreading and Concurrency

The CountDownLatch is an important concurrency utility class which was added in JDK 1.5 but unfortunately, many Java developers still struggle to understand and use this powerful tool. You can use CountDownLatch if you are spawning multiple threads to do different jobs and want to know when exactly all tasks are finished so that you can move to next stage. In other words, you can block a thread until other threads complete their task. One of the good examples where you can use CountDownLatch is an application which downloads data from a database or another application. For example, we are creating a Java program to download all Udemy courses. Since Udemy has thousands of courses, you create different threads to download different categories e.g. technology, development etc.

Your application can only be started once all data is loaded and to know the status of your loading progress you can create a CountDownLatch.

Suppose, you have spawned 5 threads to load five different categories of data then you can create a CountDownLatch with 5 counts and then bring down the count by 1 when loading of one category is finished. You can do this by calling the countDown() method.

Since different thread will take different time, your main thread can wait until all threads have completed and it can do by checking the remaining count by calling getCount() method or just calling the CountDownLatch.await() method, which causes current thread to wait until the latch has counted down to zero or the thread is interrupted.

Once the count becomes zero, it can announce that application is started and ready to accept client connections.

Here is a simplified version of Java Code for above scenario which demonstrates downloading data in multiple threads and using CountDownLatch to check completion.

CountDownLatch Example in Java


package tool;

import java.util.concurrent.CountDownLatch;

/**
 *
 * A simple example of CountDownLatch in Java
 */
public class CountDownLatchDemo {

  private static final CountDownLatch loadingLatch = new CountDownLatch(3);

  public static void main(String args[]) {

    Thread pythonCourseLoader = new Thread("PythonCourseLoader") {

      @Override
      public void run() {
        System.out.println("Loading all Python courses from Udemy..");
        // loading Python courses ....
        // loading completed, time to count down
        System.out.println("loading completed for Python courses");
        loadingLatch.countDown();
      }
    };

    Thread javaCourseLoader = new Thread("JavaCourseLoader") {
      @Override
      public void run() {
        System.out.println("Loading all Java courses from Udemy ..");
        // loading Java courses ....
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        System.out.println("loading completed for Java courses");
        loadingLatch.countDown();
      }
    };

    Thread developmentCourseLoader = new Thread("developmentCourseLoader") {
      @Override
      public void run() {
        System.out.println("Loading all Develoment courses from Udemy ..");
        // loading development courses ....
        try {
          Thread.sleep(2000);
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }

        System.out.println("loading completed for development courses");
        loadingLatch.countDown();
      }
    };

    pythonCourseLoader.start();
    javaCourseLoader.start();
    developmentCourseLoader.start();

    while (loadingLatch.getCount() != 0) {
      // wait
    }

    // loadingLatch.await();

    System.out.println("all done.");
  }
}

Output:

Loading all Python courses from Udemy..
loading completed for Python courses
Loading all Development courses from Udemy ..
Loading all Java courses from Udemy ..
loading completed for Java courses
loading completed for development courses
all done.

I have created a CountDownLatch object with 3 counts as a static final variable:

CountDownLatch loadingLatch = new CountDownLatch(3);

After that, we have three threads, which downloads data, in our case they don't do anything just sleep for 1, 2, and 3 seconds.

Every time a thread completes its execution it calls the countDown() method on the loadingLatch object.

The main() method keep checking for remaining counts using getCount() method and do whatever it wants to do only when the count reaches zero. Though I have used a while loop with getCount(), you can better use latch.await() method for waiting.

A picture is said to be worth a thousand words, so I tried to make this diagram to explain the concept to you. In this diagram you can see that our main thread is waiting on CoutnDownLatch until all thread calls the countdown and count reaches zero, after that, it progressed further.

In short, the main thread was blocked waiting for other loader thread to finish their job.

Btw, If you are not familiar with essential threading concepts e.g. wait, notify, sleep, blocking etc.

Oracle Java Tutorials and Materials, Oracle Java Learning, Oracle Java Multithreading

CountDownLatch - Important Points


Now that you know what is CountDownLatch in Java and how to use it for inter-thread communication and synchronization. It's time to revise and remember some important points:

1. The CountDownLatch utility or class is only available on JRE 1.5 or later version.

2. You cannot reuse the latch once the count reaches zero. This is the main difference between a CyclicBarrier and CountDownLatch, which can be reused.

3. The getCount() method return the current count i.e. remaining threads which have not finished yet.

4. A thread can wait on latch by calling latch.await() method to start progress after remaining thread finishes their task.

5. One of the simplest use of CountDownLatch class is to block a thread until other threads have finished their jobs.

In our example, it was the main thread which was blocked by calling the await() method of CountDownLatch until all loader class finished their job i.e. downloaded courses from Udemy.

That's all about how to use CountDownLatch in Java. It's a useful concurrency utility which can be used to keep track of completion of tasks done by multiple threads. If you are writing a Java application which loads data from another system before start functioning e.g. accepting client connections, you can use CountDownLatch to keep track of download tasks.

Related Posts