Java CountDownLatch Example
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)
CountDownLatch
with given count.
Contents
CountDownLatch Methods
Find the methods ofCountDownLatch
class.
1.
void countDown()
2.
void await() throws InterruptedException
3.
boolean await(long timeout, TimeUnit unit) throws InterruptedException
4.
long getCount()
5.
String toString()
Example-1: Waiting a pool of thread to complete
In this example, theCountDownLatch
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
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()
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 ..."); } }
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.
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();
await
causes the current thread wait until latch count reaches to zero. In our code await
is used as below.
doneSignal.await();
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; } }
Beginning the thread pool... Thread 1 working ... Thread 2 working ... Thread 1 completed ... Thread 2 completed ... Thread 3 working ... Thread 3 completed ...
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();
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 ofCountDownLatch
, 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; } }
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 aCountDownLatch
for a given timeout using await
with following declarations.
boolean await(long timeout, TimeUnit unit) throws InterruptedException
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; } }
Thread 2 working ... Thread 1 working ... Main thread working... Thread 2 completed. Thread 3 working ... Thread 1 completed. Thread 3 completed.