Chapter 15. CountDownLatch—Friend or Foe?
Alexey Soshin
Let’s imagine a situation in which we’d like to launch multiple concurrent tasks, and then wait on their completion before proceeding further. The ExecutorService makes the first part easy:
ExecutorService pool = Executors.newFixedThreadPool(8);
Future<?> future = pool.submit(() -> {
// Your task here
});
But how do we wait for all of them to complete? CountDownLatch comes to our rescue. A CountDownLatch takes the number of invocations as a constructor argument. Each task then holds a reference to it, calling the countDown method when the task completes:
int tasks = 16;
CountDownLatch latch = new CountDownLatch(tasks);
for (int i = 0; i < tasks; i++) {
Future<?> future = pool.submit(() -> {
try {
// Your task here
}
finally {
latch.countDown();
}
});
}
if (!latch.await(2, TimeUnit.SECONDS)) {
// Handle timeout
}
This example code will launch 16 tasks, then wait for them to finish before proceeding further. There are some important points to take note of, though:
-
Make sure that you release the latch in a
finallyblock. Otherwise, if an exception occurs, your main thread may wait forever. -
Use the
awaitmethod that accepts a timeout period. That way, even if you forget about the first point, your thread will wake up sooner or later. -
Check the return value of the method. It returns
falseif the time has elapsed, or
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access