CountDownLatch in Java: Usage, Examples, and Source Code Analysis

This article introduces Java's CountDownLatch synchronization tool, explains its purpose as a gate or counter, demonstrates basic and advanced usage with code examples—including a simple counter and a student race scenario—and provides an in‑depth analysis of its underlying AQS‑based source code.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
CountDownLatch in Java: Usage, Examples, and Source Code Analysis

Introduction

CountDownLatch is a multithread‑control utility in Java, often called a gate, counter, or latch. It allows one or more threads to wait until a set of operations performed by other threads completes.

Basic Concept

It works by initializing a counter with the number of threads to wait for; each call to countDown() decrements the counter, and when it reaches zero, threads blocked on await() are released.

Typical Usage

Common scenarios include coordinating component initialization during service startup or synchronizing a group of tasks such as a student race simulation.

Code Example – Simple Counter

public class TCountDownLatch {
    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(5);
        Increment increment = new Increment(latch);
        Decrement decrement = new Decrement(latch);
        new Thread(increment).start();
        new Thread(decrement).start();
        try { Thread.sleep(6000); } catch (InterruptedException e) { e.printStackTrace(); }
    }
}

class Decrement implements Runnable {
    CountDownLatch countDownLatch;
    public Decrement(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; }
    @Override
    public void run() {
        try {
            for (long i = countDownLatch.getCount(); i > 0; i--) {
                Thread.sleep(1000);
                System.out.println("countdown");
                this.countDownLatch.countDown();
            }
        } catch (InterruptedException e) { e.printStackTrace(); }
    }
}

class Increment implements Runnable {
    CountDownLatch countDownLatch;
    public Increment(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; }
    @Override
    public void run() {
        try {
            System.out.println("await");
            countDownLatch.await();
        } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("Waiter Released");
    }
}

Code Example – Student Race

public class StudentRunRace {
    CountDownLatch stopLatch = new CountDownLatch(1);
    CountDownLatch runLatch = new CountDownLatch(10);

    public void waitSignal() throws Exception {
        System.out.println("选手" + Thread.currentThread().getName() + "正在等待裁判发布口令");
        stopLatch.await();
        System.out.println("选手" + Thread.currentThread().getName() + "已接受裁判口令");
        Thread.sleep((long) (Math.random() * 10000));
        System.out.println("选手" + Thread.currentThread().getName() + "到达终点");
        runLatch.countDown();
    }

    public void waitStop() throws Exception {
        Thread.sleep((long) (Math.random() * 10000));
        System.out.println("裁判" + Thread.currentThread().getName() + "即将发布口令");
        stopLatch.countDown();
        System.out.println("裁判" + Thread.currentThread().getName() + "已发送口令,正在等待所有选手到达终点");
        runLatch.await();
        System.out.println("所有选手都到达终点");
        System.out.println("裁判" + Thread.currentThread().getName() + "汇总成绩排名");
    }

    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        StudentRunRace studentRunRace = new StudentRunRace();
        for (int i = 0; i < 10; i++) {
            Runnable runnable = () -> {
                try { studentRunRace.waitSignal(); } catch (Exception e) { e.printStackTrace(); }
            };
            service.execute(runnable);
        }
        try { studentRunRace.waitStop(); } catch (Exception e) { e.printStackTrace(); }
        service.shutdown();
    }
}

Source Code Analysis

CountDownLatch is built on top of AbstractQueuedSynchronizer (AQS). Internally it holds a final Sync object that extends AQS. The constructor creates a Sync with the initial count, which is stored as the AQS state.

The key methods are: getCount() returns the current state (the remaining count). tryAcquireShared() checks whether the state is zero; if so it returns a positive value to allow acquisition. tryReleaseShared() decrements the state and returns true when the new state becomes zero. await() invokes sync.acquireSharedInterruptibly(1), which runs AQS’s shared‑mode acquisition loop, handling interruptions and parking. countDown() calls sync.releaseShared(1), triggering the release path that eventually unparks waiting threads.

The AQS mechanisms involve a queue of Node objects, wait statuses (CANCELLED, SIGNAL, CONDITION, PROPAGATE, and 0), and methods such as doAcquireSharedInterruptibly, setHeadAndPropagate, doReleaseShared, and shouldParkAfterFailedAcquire. These manage the ordering of waiting threads, handle cancellation and time‑outs, and ensure that once the count reaches zero all waiting threads are awakened.

Conclusion

CountDownLatch provides a simple yet powerful way to coordinate threads in Java. Understanding its AQS‑based implementation helps grasp other concurrency utilities like ReentrantLock and Semaphore, making it a valuable tool for backend developers working with multithreaded applications.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaconcurrencyAQSCountDownLatch
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.