What are some key classes in java.util.concurrent (CountDownLatch, CyclicBarrier, Semaphore)?
Quick Answer
CountDownLatch lets one or more threads wait until a fixed number of countDown() calls have completed, then it opens permanently and cannot be reset. CyclicBarrier makes a fixed number of threads all wait for each other at a common point before any proceed, and it can be reused for repeated rounds. Semaphore controls access to a limited number of permits, letting only N threads through a resource at once, generalizing a lock (which is effectively a semaphore with 1 permit).
Detailed Answer
Three widely-used coordination utilities from java.util.concurrent, each solving a distinct pattern:
CountDownLatch — one or more threads wait for a set of operations (potentially in other threads) to finish, tracked by a countdown from an initial number to zero. One-shot: once it reaches zero, it stays open forever; it cannot be reset or reused.
CountDownLatch latch = new CountDownLatch(3);
// 3 worker threads each call latch.countDown() when done
latch.await(); // main thread blocks until count reaches 0
Typical use: wait for several parallel startup tasks to finish before proceeding, or have a main thread wait for N worker threads to complete.
CyclicBarrier — a fixed number of threads all wait for each other at a common barrier point; once the last one arrives, all are released simultaneously. Unlike CountDownLatch, it's reusable — it automatically resets for the next "round" once released (hence "cyclic"), and supports an optional action run once all parties arrive.
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("all arrived"));
barrier.await(); // each of 3 threads blocks here until all 3 have called await()
Typical use: parallel simulation steps where every worker must finish step N before any starts step N+1.
Semaphore — maintains a set number of permits; threads acquire() a permit (blocking if none are available) and release() it when done, limiting how many threads can access a resource concurrently. A Semaphore with 1 permit behaves like a (non-reentrant) lock; with N permits, it caps concurrent access at N.
Semaphore semaphore = new Semaphore(5); // at most 5 concurrent accesses
semaphore.acquire();
try { accessLimitedResource(); } finally { semaphore.release(); }
Typical use: throttling concurrent connections to a database or external service to a fixed maximum.