Understanding CountDownLatch With Simple Example
We use Threads to run multiple tasks in parallel. We usually create a thread, start them, and at a later point in the application, we wait for the thread to join back. Below is the simple example which shows how it works.
We created three instances of Task (which extends thread), then started them and then finally called join() on each thread. We called join() on each thread because we want to make sure that all child threads are completed execution before main Thread exits. The run() method in the Task is just blocking the thread for a couple of seconds to mimic a long-running job. After the sleep, it prints its name in the console.
This simple example works fine for a small number of threads, but what if, if we want to create more threads and wait for all of them to join()? Like for example, ten threads or maybe a hundred threads? The approach, as mentioned earlier, is not suitable for more threads because we need to declare and maintain multiple Thread instances. CountDownLatch will rescue us from this problem.
We will initialize a CountDownLatch object with a count; this count should be equal to the number of Threads. Means if we want to run ten Threads and wait for all of them to finish, then we will initialize CountDownLatch with ten. The below example shows the initialization of CountDownLatch with three because we want to start and wait for three threads.
CountDownLatch works like a counter, and we need to pass the instance of CountDownLatch to each thread. When each thread completes its job, then they need to count this counter down by calling countDown() on CountDownLatch. By the time all threads complete their tasks, then this counter will be zero. The below code shows how it works; this time, I used ExecutorService to run threads because this way, I no need to create Thread instances.
We passed CountDownLatch to each Thread, and within the run() method, we called countDownLatch.countDown() to decrement the counter.
countDownLatch.await() causes the current thread to wait until the latch has counted down to zero. Finally, we are shutting down ExecutorService and printing a message to console.
What if a thread doesn’t count down? Then the main thread waits indefinitely. To fix this, we can use await(long timeout, TimeUnit unit), which waits for a specific time and returns boolean, this boolean tells us if all threads ran successfully or not.
In this article, we learned about CountDownLatch and went through different examples to understand how it works.