Understanding CountDownLatch and CompletableFuture in Java Concurrency
This article explains the purpose, typical usage scenarios, and provides concrete code demonstrations of Java's CountDownLatch and CompletableFuture, comparing their synchronization versus asynchronous capabilities and guiding developers on selecting the appropriate tool for effective multithreaded programming.
In the world of Java concurrent programming, CountDownLatch and CompletableFuture are two essential utilities that help manage and coordinate the execution of multiple threads.
CountDownLatch
Imagine you are a project manager waiting for several teams to finish their tasks before proceeding. In Java, CountDownLatch acts as a helper that uses a counter to control when waiting threads are released. The counter is initialized with the number of threads to wait for, each thread decrements the counter when it finishes, and when the counter reaches zero all waiting threads continue.
Code Example
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
final int totalThreads = 3;
CountDownLatch latch = new CountDownLatch(totalThreads);
for (int i = 0; i < totalThreads; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " 正在工作");
try {
Thread.sleep(1000); // 模拟工作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 完成工作");
latch.countDown(); // 计数减一
}).start();
}
System.out.println("主线程等待所有子线程完成");
latch.await(); // 等待计数器为零
System.out.println("所有子线程完成,主线程继续执行");
}
}The main thread waits until the three worker threads finish their simulated work before proceeding.
CompletableFuture: The Swiss Army Knife of Asynchronous Programming
Java 8 introduced CompletableFuture , a powerful tool for asynchronous programming. It supports fluent chaining, handling of asynchronous results, and easy composition of multiple asynchronous tasks.
Code Example
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CompletableFutureExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
CompletableFuture
future = CompletableFuture.runAsync(() -> {
System.out.println("异步任务1执行");
}, executor)
.thenRunAsync(() -> {
System.out.println("异步任务2执行");
}, executor);
future.join(); // 等待异步任务完成
executor.shutdown();
}
}This example creates two asynchronous tasks that execute sequentially on a fixed‑size thread pool.
Differences
Both CountDownLatch and CompletableFuture are Java concurrency tools, but they serve different purposes.
CountDownLatch
Main Features:
Works with a counter initialized to a specific value.
The countDown() method decrements the counter.
The await() method blocks until the counter reaches zero.
Typical Use Cases: Waiting for a group of operations to complete before proceeding.
CompletableFuture
Main Features:
Executes tasks asynchronously.
Supports callbacks that run when a task completes.
Allows composition of multiple asynchronous tasks.
Typical Use Cases: Asynchronous programming where tasks need to be chained or combined.
Summary
CountDownLatch is used for synchronously waiting for a set of operations to finish, while CompletableFuture is used for asynchronous programming and task composition.
CountDownLatch generally provides simple synchronization, whereas CompletableFuture offers richer features such as exception handling and task combination.
Choosing the right tool depends on whether you need a blocking wait (use CountDownLatch ) or a non‑blocking, composable asynchronous workflow (use CompletableFuture ).
Top Architecture Tech Stack
Sharing Java and Python tech insights, with occasional practical development tool tips.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.