Can someone help me to understand what Java CountDownLatch
is and when to use it?
I don't have a very clear idea of how this program works. As I understand all three threads start at once and each Thread will call CountDownLatch after 3000ms. So count down will decrement one by one. After latch becomes zero the program prints "Completed". Maybe the way I understood is incorrect.
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Processor implements Runnable {
private CountDownLatch latch;
public Processor(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
System.out.println("Started.");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
}
// -----------------------------------------------------
public class App {
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(3); // coundown from 3 to 0
ExecutorService executor = Executors.newFixedThreadPool(3); // 3 Threads in pool
for(int i=0; i < 3; i++) {
executor.submit(new Processor(latch)); // ref to latch. each time call new Processes latch will count down by 1
}
try {
latch.await(); // wait until latch counted down to 0
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Completed.");
}
}
CoundDownLatch enables you to make a thread wait till all other threads are done with their execution.
Pseudo code can be:
Yes, you understood correctly.
CountDownLatch
works in latch principle, the main thread will wait until the gate is open. One thread waits for n threads, specified while creating theCountDownLatch
.Any thread, usually the main thread of the application, which calls
CountDownLatch.await()
will wait until count reaches zero or it's interrupted by another thread. All other threads are required to count down by callingCountDownLatch.countDown()
once they are completed or ready.As soon as count reaches zero, the waiting thread continues. One of the disadvantages/advantages of
CountDownLatch
is that it's not reusable: once count reaches zero you cannot useCountDownLatch
any more.Edit:
Use
CountDownLatch
when one thread (like the main thread) requires to wait for one or more threads to complete, before it can continue processing.A classical example of using
CountDownLatch
in Java is a server side core Java application which uses services architecture, where multiple services are provided by multiple threads and the application cannot start processing until all services have started successfully.P.S. OP's question has a pretty straightforward example so I didn't include one.
It is used when we want to wait for more than one thread to complete its task. It is similar to join in threads.
Where we can use CountDownLatch
Consider a scenario where we have requirement where we have three threads "A", "B" and "C" and we want to start thread "C" only when "A" and "B" threads completes or partially completes their task.
It can be applied to real world IT scenario
Consider a scenario where manager divided modules between development teams (A and B) and he wants to assign it to QA team for testing only when both the teams completes their task.
Output of above code will be:
Task assigned to development team devB
Task assigned to development team devA
Task finished by development team devB
Task finished by development team devA
Task assigned to QA team
Task finished by QA team
Here await() method waits for countdownlatch flag to become 0, and countDown() method decrements countdownlatch flag by 1.
Limitation of JOIN: Above example can also be achieved with JOIN, but JOIN can not be used in two scenarios:
This example from Java Doc helped me understand the concepts clearly:
Visual interpretation:
Evidently,
CountDownLatch
allows one thread (hereDriver
) to wait until a bunch of running threads (hereWorker
) are done with their execution.From oracle documentation about CountDownLatch:
A
CountDownLatch
is initialized with a given count. Theawait
methods block until the current count reaches zero due to invocations of thecountDown()
method, after which all waiting threads are released and any subsequent invocations of await return immediately. This is a one-shot phenomenon -- the count cannot be reset.A
CountDownLatch
initialized with a count of one serves as a simple on/off latch, or gate: all threads invoking await wait at the gate until it is opened by a thread invoking countDown().A
CountDownLatch
initialized to N can be used to make one thread wait until N threads have completed some action, or some action has been completed N times.If the current count is zero then this method returns immediately.
If the current count is greater than zero then it is decremented. If the new count is zero then all waiting threads are re-enabled for thread scheduling purposes.
Explanation of your example.
You have set count as 3 for
latch
variableYou have passed this shared
latch
to Worker thread :Processor
Runnable
instances ofProcessor
have been submitted toExecutorService
executor
Main thread (
App
) is waiting for count to become zero with below statementProcessor
thread sleeps for 3 seconds and then it decrements count value withlatch.countDown()
First
Process
instance will change latch count as 2 after it's completion due tolatch.countDown()
.Second
Process
instance will change latch count as 1 after it's completion due tolatch.countDown()
.Third
Process
instance will change latch count as 0 after it's completion due tolatch.countDown()
.Zero count on latch causes main thread
App
to come out fromawait
App program prints this output now :
Completed