<img alt="" src="https://secure.leadforensics.com/150446.png " style="display:none;">

Synchronizers In Java - CountDownLatch

Madhura Oak Oct 05, 2012

synchronizer Java ExecutorService Multithreading latch Concurrency API CountDownLatch Technology synchronizers

The Concurrency API introduced in Java 5 provides a latch – CountDownLatch. A latch is a synchronizer which acts like a gate. CountDownLatch acts like a one-time closed gate which is initially closed and can be opened only once. Once it is opened it will remain open.

In a multi-threaded application, a thread may need to wait until a set of threads have completed some execution. Usually, wait() and notify() methods are used when one thread has to wait until some other thread has performed some execution. When the other thread calls notify() on the same object, the thread which went first in the WAITING state can be granted monitor lock by the thread scheduler for execution. In case there are many waiting threads, the notifyAll() will cause all the waiting threads to come out of the WAITING state. However, these wait() and notify() or notifyAll() calls need to be made within the synchronized block or method on the same object.

When multiple threads are running and we want to wait until all the threads have reached a certain point of execution and then perform some task, programming such a logic using wait-notifyAll or Condition can be quite complex. We may need to use a counter to keep track of how many threads have reached that execution point or are yet to reach and may need to check this counter before calling notifyAll. A cleaner solution to implement this logic is to use CountDownLatch.

A CountDownLatch constructor takes an int argument. It is usually the count of threads. The countDown() method of this class decrements the count by 1. The thread which calls the await() method of this class goes into the WAITING state and will keep waiting until the count has reached zero or some other thread interrupts it. The current count can be obtained by calling the getCount() method of this class. A timed await() method also exists in this class which waits until the timeout has elapsed or the waiting thread is interrupted by some other thread or the latch count has reached zero. This method can be used to avoid the threads to keep waiting for long time. Since await() is a blocking method, the checked exception InterruptedException needs to be handled.

The CountDownLatch acts like a latch or gate which is opened when the count reaches zero. The count in CountDownLatch cannot be reset after its instance is created. When the count reaches zero, the await() method will no longer make the threads go in WAITING state. Thus, the CountDownLatch is a one-shot latch.

The set of threads which should wait until a certain point of execution is reached, share the CountDownLatch instance. Unlike wait-notify methods, synchronized block/method is not required to use CountDownLatch. The CountDownLatch is also thread-safe.

Listing 1 given below demonstrates the use of CountDownLatch. The RandomNumberGenerator class is an implementation of Runnable which prints 10 random numbers. The main thread creates a CountDownLatch instance with count 5. This instance is shared amongst the RandomNumberGenerator instances. The main thread creates a fixed size thread pool of maximum 5 threads, generates RandomNumberGenerator instances and submits them to the ExecutorService. The ExecutorService dispatches a thread from the thread pool to executes the run() method. After the Runnable tasks are submitted, we want the main thread to wait until the execution of all threads is over. Hence, the await() method is called on the CountDownLatch. Since, this is called by the main thread, it will keep waiting until the count in CountDownLatch instance reaches zero. Once the thread executing RandomNumberGenerator has printed 10 random numbers on the console, the countDown() method is called on the CountDownLatch which means that one thread has completed executing its task. Thus, when the count in CountDownLatch reaches zero, the main thread can start executing the next statements after await() call.

public class RandomNumberGenerator implements Runnable {
private Random random = new Random();
private CountDownLatch latch;
public void setLatch(CountDownLatch latch) {
this.latch = latch;
}	
public void run() {
for(int i=1; i <= 10; i++) {
System.out.println(random.nextInt());
}
latch.countDown();
}
}
public class CountDownLatchDemo {
public static void main(String args[])
throws InterruptedException {
final int COUNT = 5;
CountDownLatch latch = new CountDownLatch(COUNT);
ExecutorService service =
Executors.newFixedThreadPool(COUNT);
System.out.println(
"printing random numbers started...");
for(int i=1; i <= COUNT; i++) {
RandomNumberGenerator generator =
new RandomNumberGenerator();
generator.setLatch(latch);
service.submit(generator);
}
latch.await();
System.out.println(
"printing random numbers stopped...";);
}
}

Listing 1. A progam using CountDownLatch

ExecutorService.awaitTermination()

The awaitTermination() method of ExecutorService can be called to put the thread executing this method in TIMED_WAITING state until all the threads complete execution after shutdown() is called or the specified timeout period in the method is over or some other thread interrupts the waiting thread.

The difference between calling awaitTermination() on ExecutorService and using the CountDownLatch as given in Listing 1 is that the awaitTermination() can be called only after shutdown() is called. ExecutorService cannot except new tasks for execution after shutdown() is called. Whereas with the use of CountDownLatch as shown in Listing 1, new tasks can be submitted to the ExecutorService after latch.await() is called.

Similar Blog

e-Zest is a leading digital innovation partner for enterprises and technology companies that utilizes emerging technologies for creating engaging customers experiences. Being a customer-focused and technology-driven company, it always helps clients in crafting holistic business value for their software development efforts. It offers software development and consulting services for cloud computing, enterprise mobility, big data and analytics, user experience and digital commerce.