Careeroza
CountDownLatch and Other Synchronizers
The Synchronizers
| Class | Idea | Example |
|---|---|---|
CountDownLatch | wait until N events happened (one-shot) | start the app after 3 services are ready |
CyclicBarrier | N threads wait for each other, reusable | game round starts when all players are ready |
Semaphore | at most N permits at a time | max 10 DB connections, rate limits |
Phaser | flexible multi-phase barrier | multi-step batch jobs |
Exchanger | two threads swap objects | double buffering |
CountDownLatch: Wait for Startup Checks
Example
Workers record their result in a thread-safe list; main prints after await(), sorted, so output is stable.
import java.util.*;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws InterruptedException {
List<String> checks = List.of("database", "redis", "payment-gateway");
CountDownLatch ready = new CountDownLatch(checks.size());
Queue<String> results = new ConcurrentLinkedQueue<>();
for (String c : checks) {
Thread.ofPlatform().start(() -> {
results.add(c + " OK");
ready.countDown();
});
}
boolean allReady = ready.await(5, TimeUnit.SECONDS);
results.stream().sorted().forEach(System.out::println);
System.out.println("All checks passed: " + allReady + " -> starting server");
}
}Output
database OK payment-gateway OK redis OK All checks passed: true -> starting server
Semaphore: Limit Concurrency
Example
10 tasks share an API that allows only 3 calls at a time. The program tracks the highest number of simultaneous calls.
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class Main {
public static void main(String[] args) {
Semaphore permits = new Semaphore(3);
AtomicInteger inFlight = new AtomicInteger();
AtomicInteger maxSeen = new AtomicInteger();
AtomicInteger done = new AtomicInteger();
try (ExecutorService pool = Executors.newFixedThreadPool(10)) {
for (int i = 0; i < 10; i++) {
pool.submit(() -> {
try {
permits.acquire();
try {
int now = inFlight.incrementAndGet();
maxSeen.accumulateAndGet(now, Math::max);
Thread.sleep(50);
inFlight.decrementAndGet();
done.incrementAndGet();
} finally { permits.release(); }
} catch (InterruptedException e) { Thread.currentThread().interrupt(); }
});
}
}
System.out.println("Calls done: " + done.get());
System.out.println("Never more than 3 at once: " + (maxSeen.get() <= 3));
}
}Output
Calls done: 10 Never more than 3 at once: true