CountDownLatch and Semaphore
Wait for a batch of work to finish, and cap how many threads may enter a section at once.
Open this lesson in the learning hubKey points
CountDownLatchis a one-shot gate.await()blocks untilcountDown()has driven the count to zero.- It never resets. If you need the same barrier round after round, that is
CyclicBarrier. - Always
countDown()in afinally. One failing task that skips it hangs every waiter. Semaphorehands out N permits:acquire()takes one,release()gives it back. Ideal for connection caps and rate limits.- A
Semaphore(1)behaves like a lock but has no owner, so any thread can release it. That is occasionally useful and often a bug.
Example
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String[] args) throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(6);
CountDownLatch finished = new CountDownLatch(6); // counts down to zero, once
Semaphore permits = new Semaphore(2); // at most 2 inside at a time
AtomicInteger inside = new AtomicInteger();
AtomicInteger peak = new AtomicInteger();
for (int i = 0; i < 6; i++) {
pool.execute(() -> {
try {
permits.acquire();
try {
peak.accumulateAndGet(inside.incrementAndGet(), Math::max);
Thread.sleep(50);
inside.decrementAndGet();
} finally { permits.release(); } // release in finally, always
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally { finished.countDown(); }
});
}
finished.await(); // wait for all six
System.out.println("all 6 workers done");
System.out.println("peak concurrency: " + peak.get() + " (semaphore allows 2)");
pool.shutdown();
pool.awaitTermination(5, TimeUnit.SECONDS);
}
}
Latch waits for work to finish. Semaphore limits who gets in.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Multithreading course, and every lesson in it is listed on the Multithreading contents page.