Backend Development 8 min read

Understanding and Using CountDownLatch in Java for Thread Coordination

This article explains the concept of Java's CountDownLatch, compares it with join(), demonstrates how to coordinate thread‑pool tasks using the latch, provides complete example code, and details its internal mechanism and common methods for synchronizing concurrent operations.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Understanding and Using CountDownLatch in Java for Thread Coordination

Wait for Threads with CountDownLatch

The article introduces the problem of needing to wait for multiple threads or thread‑pool tasks to finish before proceeding with the main thread, and relates this to the gaming concept of waiting for all teammates before starting a team fight.

Creating Threads with join()

// 创建线程1
Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        // do something
    }
});
t1.start();

// 创建线程2
Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
        // do something
    }
});
t2.start();

// 等待线程 1和线程 2 执行完
t1.join();
t2.join();

Using join() works when threads are created directly, but in real applications tasks are usually submitted to a thread pool, which does not provide a join() method.

ThreadPool and the Need for CountDownLatch

// 创建固定线程数的线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 任务一
executorService.submit(new Runnable() {
    @Override
    public void run() {
        // do something
    }
});
// 任务二
executorService.submit(new Runnable() {
    @Override
    public void run() {
        // do something
    }
});

Because the thread pool lacks join() , we need a coordination mechanism; this is where CountDownLatch comes into play.

CountDownLatch Usage

public static void main(String[] args) throws InterruptedException {
    // 创建 CountDownLatch
    CountDownLatch countDownLatch = new CountDownLatch(2);

    // 创建固定线程数的线程池
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    // 任务一
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(1200); // 让此任务执行 1.2s
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("我是任务一");
            countDownLatch.countDown();
        }
    });
    // 任务二
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(1000); // 让此任务执行 1.0s
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("我是任务二");
            countDownLatch.countDown();
        }
    });

    // 等待任务执行完成
    countDownLatch.await();
    System.out.println("程序执行完成~");
}

The program prints the two task messages after their respective sleeps and finally prints "程序执行完成~" only after both tasks have called countDown() , demonstrating that the main thread waited for all workers.

CountDownLatch Working Principle

CountDownLatch holds an internal volatile counter initialized with the value passed to its constructor. Each call to countDown() decrements the counter. Calls to await() block the current thread until the counter reaches zero, at which point waiting threads are released.

Execution Flow

The latch’s await() method checks the counter; if it is not zero, the thread enters a waiting state. When other threads invoke countDown() and the counter becomes zero, all waiting threads are awakened and continue execution.

Common Methods

// Blocks until count reaches 0
public void await() throws InterruptedException { }

// Blocks until count reaches 0 or timeout expires
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }

// Decrements the count by one
public void countDown() { }

Conclusion

CountDownLatch provides a simple way to make a thread wait until a set of other threads have completed their work, similar to waiting for all players to gather before starting a team fight in a game. By initializing the latch with a positive count and calling countDown() after each task, the main thread can reliably synchronize concurrent operations.

Reference & Acknowledgements

Source: www.jianshu.com/p/128476015902

JavaConcurrencythreadpoolSynchronizationCountDownLatch
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

login 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.