Java CountDownLatch Example

By Arvind Rai, June 14, 2022
On this page we will learn using Java CountDownLatch in our application.
1. The CountDownLatch is a synchronization aid that allows one or more threads to wait until a set of operations, being performed in other threads, completes.
2. The CountDownLatch is initialized with a given count. Its method countDown() decrements the count and await() causes the current thread to wait until it has counted down to zero.
3. The CountDownLatch initialized with count 1, can be used as simple on/off latch or gate. All threads invoking await(), will wait until a thread invokes countDown().
4. The CountDownLatch initialized with count N, can be used to make one thread wait until N threads have completed its job.
5. The CountDownLatch can be terminated for a given timeout even if threads have not completed its job.
6. The CountDownLatch is a one-shot phenomenon because the count cannot be reset.
7. The constructor of CountDownLatch is declared as following.
CountDownLatch(int count) 
This initializes the CountDownLatch with given count.

CountDownLatch Methods

Find the methods of CountDownLatch class.
1.
void countDown() 
Decrements the count of the latch and releases all waiting threads when the count reaches zero.
2.
void await() throws InterruptedException 
Causes the current thread to wait until the latch has counted to zero, unless the thread is interrupted.
3.
boolean await(long timeout, TimeUnit unit) throws InterruptedException 
Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted, or the specified waiting time elapses.
4.
long getCount() 
Returns the current count.
5.
String toString() 
Returns a string identifying this latch, as well as its state.

Example-1: Waiting a pool of thread to complete

In this example, the CountDownLatch is used to wait a pool of threads to complete. In our demo, main thread will wait for a thread pool to compete its tasks. To achieve this, we use await and countdown methods of CountDownLatch class.

(a) await
void await() throws InterruptedException 
This method causes the current thread to wait. The thread waiting gets over by two ways.
1. If latch count reaches to zero, it returns immediately with true value. Latch count is decremented by using countdown method.
2. If some other thread interrupts the current thread.

(b) countDown
void countDown() 
It decrements the latch count by one. If the latch count reaches to zero, the waiting time of await() is over. If latch count is zero, then nothing happens.

Look into the code.
CountDownLatchDemo1.java
package com.concretepage;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo1 {
  public static void main(String... args) throws InterruptedException {
	int count = 5;
	CountDownLatch doneSignal = new CountDownLatch(count);
	ExecutorService executorService = Executors.newFixedThreadPool(2);
	for (int threadNum = 1; threadNum <= count; ++threadNum) {
	  executorService.execute(new Worker(doneSignal, threadNum));
	}
	doneSignal.await();
	System.out.println("All threads completed.");
	executorService.shutdown();
  }
}
class Worker implements Runnable {
  private final CountDownLatch doneSignal;
  private final int threadNum;
  Worker(CountDownLatch doneSignal, int threadNum) {
	this.doneSignal = doneSignal;
	this.threadNum = threadNum;
  }
  public void run() {
	doWork();
	doneSignal.countDown();
	System.out.println("Thread " + threadNum + " completed.");
  }
  void doWork() {
	System.out.println("Thread " + threadNum + " working ...");
  }
} 
Output
Thread 1 working ...
Thread 1 completed.
Thread 3 working ...
Thread 3 completed.
Thread 4 working ...
Thread 4 completed.
Thread 5 working ...
Thread 5 completed.
Thread 2 working ...
Thread 2 completed.
All threads completed. 
1. We have created a Runnable class i.e. Worker.
2. The CountDownLatch has been instantiated with count 5.
3. A thread pool has been created with pool size 2.
4. Five instances of Runnable worker has been executed. Each worker is counting down the latch after completing its task as below.
doneSignal.countDown(); 
5. The await causes the current thread wait until latch count reaches to zero. In our code await is used as below.
doneSignal.await(); 
It is causing main thread to wait.
6. When the latch count reaches to zero, the await method immediately returns. In our code, doneSignal.countDown() is executed five times and finally latch count reaches to zero and doneSignal.await() returns immediately and then main thread starts executing.

Example-2: Waiting a pool of thread to begin

In this example, CountDownLatch is used to wait a pool of thread to begin. We will create a thread pool and submit the tasks. Each task will wait until a thread starts them.
Find the code.
CountDownLatchDemo2.java
package com.concretepage;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo2 {
  public static void main(String... args) throws InterruptedException {
	int count = 1;
	CountDownLatch beginSignal = new CountDownLatch(count);
	ExecutorService executorService = Executors.newFixedThreadPool(2);
	for (int threadNum = 1; threadNum <= 3; ++threadNum) {
	  executorService.execute(createRunnableTask(beginSignal, threadNum));
	}
	System.out.println("Beginning the thread pool...");
	beginSignal.countDown();
  }
  static Runnable createRunnableTask(CountDownLatch beginSignal, int threadNum) {
	Runnable task = () -> {
	    try {
		  beginSignal.await();
		  System.out.println("Thread " + threadNum + " working ...");
		  Thread.sleep(2000);
		  System.out.println("Thread " + threadNum + " completed ...");
		} catch (InterruptedException e) {
		  e.printStackTrace();
		}
	};
	return task;
  }
} 
Output
Beginning the thread pool...
Thread 1 working ...
Thread 2 working ...
Thread 1 completed ...
Thread 2 completed ...
Thread 3 working ...
Thread 3 completed ... 
In our example
1. The CountDownLatch has been initiated with count 1.
2. A thread pool has been created with pool size 2.
3. Three tasks have been submitted to thread pool. Initially they will wait because of below line of code.
beginSignal.await(); 
4. In the main thread, once we call beginSignal.countDown(), the latch count reaches to zero and then all beginSignal.await() returns immediately making waiting time over.

Example-3: Waiting a pool of thread to begin and complete

In this example, we have created two instances of CountDownLatch, one for waiting all threads to begin, and another for waiting main thread to let all threads finish their tasks.
CountDownLatchDemo3.java
package com.concretepage;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo3 {
  public static void main(String... args) throws InterruptedException {
	CountDownLatch beginSignal = new CountDownLatch(1);
	CountDownLatch doneSignal = new CountDownLatch(3);
	ExecutorService executorService = Executors.newFixedThreadPool(2);
	for (int threadNum = 1; threadNum <= 3; ++threadNum) {
	  executorService.execute(createRunnableTask(beginSignal, doneSignal, threadNum));
	}
	System.out.println("Beginning the thread pool...");
	beginSignal.countDown();
	doneSignal.await();
	System.out.println("All threads completed.");
	executorService.shutdown();
  }
  static Runnable createRunnableTask(CountDownLatch beginSignal, CountDownLatch doneSignal, int threadNum) {
	Runnable task = () -> {
	    try {
		  beginSignal.await();
		  System.out.println("Thread " + threadNum + " working ...");
		  Thread.sleep(2000);
		  System.out.println("Thread " + threadNum + " completed.");
		  doneSignal.countDown();
		} catch (InterruptedException e) {
		  e.printStackTrace();
		}
	};
	return task;
  }
} 
Output
Beginning the thread pool...
Thread 1 working ...
Thread 2 working ...
Thread 2 completed.
Thread 1 completed.
Thread 3 working ...
Thread 3 completed.
All threads completed. 

Example-4: Terminate CountDownLatch

We can terminate a CountDownLatch for a given timeout using await with following declarations.
boolean await(long timeout, TimeUnit unit) throws InterruptedException 
This method causes current thread to wait. The waiting can be interrupted by three ways.
1. If the current latch count reaches to zero, this method returns immediately with true value. Latch count is decremented by countDown() method by current thread.
2. If some other thread interrupts the current thread.
3. If specified waiting time elapses, the method returns immediately with false value.

Find the example.
CountDownLatchDemo4.java
package com.concretepage;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class CountDownLatchDemo4 {
  public static void main(String... args) throws InterruptedException {
	CountDownLatch doneSignal = new CountDownLatch(3);
	ExecutorService executorService = Executors.newFixedThreadPool(2);
	for (int threadNum = 1; threadNum <= 3; ++threadNum) {
	  executorService.execute(createRunnableTask(doneSignal, threadNum));
	}
	doneSignal.await(2, TimeUnit.SECONDS);
	System.out.println("Main thread working...");
	executorService.shutdown();
  }
  static Runnable createRunnableTask(CountDownLatch doneSignal, int threadNum) {
	Runnable task = () -> {
	  try {
		System.out.println("Thread " + threadNum + " working ...");
		Thread.sleep(3000);
		System.out.println("Thread " + threadNum + " completed.");		
		doneSignal.countDown();
	  } catch (InterruptedException e) {
		e.printStackTrace();
	  }
	};
	return task;
  }
} 
Output
Thread 2 working ...
Thread 1 working ...
Main thread working...
Thread 2 completed.
Thread 3 working ...
Thread 1 completed.
Thread 3 completed. 

Reference

Class CountDownLatch
POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us