Java CountDownLatch – A Nifty Synchronization Aid

Filed Under: Java
Java CountDownLatch

Java CountDownLatch class is part of Concurrency API. It allows us to create a synchronization, where a thread waits until the count down is 0. It’s useful when we want a thread to wait on a finite number of other threads to finish processing.

How Does CountDownLatch Works?

  • The CountDownLatch instance is created with a given count.
  • When a thread calls CountDownLatch await() method, it waits until the count is 0.
  • It’s the responsibility of the other threads to call CountDownLatch countDown() method, when they are done. Every call to countDown() method reduces the count value by 1.
  • When all the other threads have called the countDown() method, the count becomes 0 and the threads waiting because of await(), starts their execution.
  • The value of count can’t be reset, so once a CountDownLatch work is finished, we can’t reuse the same instance. Any further calls to await() will not cause any blocking of the thread.

Java CountDownLatch Example

Let’s look at a simple example of CountDownLatch in a multi-threaded application.


package com.journaldev.concurrency;

import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {

	public static void main(String[] args) {
		CountDownLatch latch = new CountDownLatch(3);
		Random random = new Random();

		WorkerThread wt1 = new WorkerThread(latch, random.nextInt(5000));
		WorkerThread wt2 = new WorkerThread(latch, random.nextInt(5000));
		WorkerThread wt3 = new WorkerThread(latch, random.nextInt(5000));

		new Thread(wt1, "WT-11").start();
		new Thread(wt2, "WT-22").start();
		new Thread(wt3, "WT-33").start();

		try {
			latch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("Finishing the Main Method");
	}

}

class WorkerThread implements Runnable {

	private CountDownLatch latch;
	private int delay;

	public WorkerThread(CountDownLatch latch, int delay) {
		this.latch = latch;
		this.delay = delay;
	}

	@Override
	public void run() {
		String name = Thread.currentThread().getName();
		int delay = this.delay;

		System.out.println(name + " sleeping for " + delay + " milliseconds.");
		try {
			Thread.sleep(delay);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		this.latch.countDown();
		System.out.println(name + " finished");

	}

}
  1. We have 3 worker threads and we want our main thread to wait until all of them are finished. So we initialize the CountDownLatch with count 3.
  2. In the worker thread, we are calling countDown() method on the CountDownLatch instance. So, when all the 3 worker threads are done with their processing, the count will become 0 and the main thread waiting because of await() will start its execution.
  3. The main thread is blocked because of CountDownLatch await() call. As soon as the count becomes 0, it starts executing.
  4. We make sure that all the worker threads are executed before we finish the main thread, with the help of CountDownLatch synchronization mechanism.

A possible output of the above program would be as follows:


WT-33 sleeping for 2962 milliseconds.
WT-22 sleeping for 3874 milliseconds.
WT-11 sleeping for 1746 milliseconds.
WT-11 finished
WT-33 finished
WT-22 finished
Finishing the Main Method

CountDownLatch await()

There are two version of await() method.

  1. await(): waits indefinitely for the count to become 0, unless the thread is interrupted.
  2. await(long timeout, TimeUnit unit): waits for the count to become 0 with the given timeout value. If the timeout occurs, the method stops blocking and returns false.

CountDownLatch vs CyclicBarrier

  • The CountDownLatch provides a mechanism to wait for the count to become 0 whereas CyclicBarrier provides a mechanism to create a common barrier “count” that is reached by every thread await() calls.
  • The CountDownLatch operations are irreversible, once the count is 0, any further calls to await() won’t block the thread. As the name CyclicBarrier suggests, it’s cyclic in nature and the barrier is reused again after the waiting threads are released.
  • CountDownLatch is useful when we want to wait on a specific set of threads to execute. The CyclicBarrier is useful when we have a number of threads and we want to wait only when a certain number of them are executed.

References

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages