Backend Development 12 min read

Understanding CountDownLatch, CyclicBarrier, Semaphore, and Exchanger in Java

This article explains Java’s concurrency utilities CountDownLatch, CyclicBarrier, Semaphore, and Exchanger, illustrating their concepts with race‑style analogies, providing complete code examples, and showing execution results to demonstrate how threads can synchronize, wait, limit, and exchange data.

Top Architect
Top Architect
Top Architect
Understanding CountDownLatch, CyclicBarrier, Semaphore, and Exchanger in Java

CountDownLatch

CountDownLatch works like a latch with N locks; the latch opens only after all N locks are released. It is illustrated with a race example where a referee waits for all runners to be ready before firing the start gun.

The two main methods are await() , which blocks the calling thread until the latch reaches zero, and countDown() , which decrements the latch count.

public class TestCountDownLatch {
    public static void main(String[] args) {
        // Need to wait for two threads, so pass 2
        CountDownLatch latch = new CountDownLatch(2);
        // Thread 1 runs for 1 second
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("1号选手准备就绪!用时1秒!");
                latch.countDown();
            }
        }).start();

        // Thread 2 runs for 3 seconds
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("2号选手准备就绪!用时3秒!");
                latch.countDown();
            }
        }).start();

        try {
            System.out.println("请1号选手和2号选手各就各位!");
            // Main thread waits until both threads finish
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // After both threads finish, main thread continues
        System.out.println("裁判发枪,1号选手和2号选手开跑!");
    }
}

Running result with the latch shows the referee waiting until both runners are ready before starting the race. Without the latch, the start gun fires early, leading to a chaotic order.

CyclicBarrier

CyclicBarrier acts like a fence that makes a set of threads wait for each other. It can be reused for multiple cycles, allowing threads to repeatedly synchronize at a common barrier point.

Unlike CountDownLatch, where one thread waits for others, CyclicBarrier makes all participating threads wait for each other before proceeding to the next round.

public class TestCyclicBarrier {
    // 1号选手跑的轮数
    public static int countA = 1;
    // 2号选手跑的轮数
    public static int countB = 1;
    public static void main(String[] args) {
        // 2 threads will wait for each other
        CyclicBarrier barrier = new CyclicBarrier(2);

        new Thread(new Runnable() {
            @Override
            public void run() {
                // Run three rounds
                for (int i = 0; i < 3; i++) {
                    System.out.println("1号选手开始跑!当前第" + countA++ + "轮比赛!");
                    // Simulate slower runner (3 seconds)
                    try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
                    try {
                        System.out.println("1号选手抵达终点!");
                        barrier.await();
                    } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                // Run three rounds
                for (int i = 0; i < 3; i++) {
                    System.out.println("2号选手开始跑!当前第" + countB++ + "轮比赛!");
                    // Faster runner (1 second)
                    try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
                    try {
                        System.out.println("2号选手抵达终点!");
                        barrier.await();
                    } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); }
                }
            }
        }).start();
    }
}

The output shows each round where both runners reach the finish line, wait at the barrier, and then start the next round together. Removing the barrier makes the faster runner finish all rounds before the slower one catches up.

Semaphore

Semaphore controls access to a limited number of permits. Threads acquire a permit before proceeding and release it when done. It is demonstrated with a ticket‑selling scenario where only two tickets are issued each hour.

public class TestSemaphore {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(0);
        System.out.println("顾客在售票处等候中");
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(500);
                        // Wait for ticket
                        semaphore.acquire();
                        System.out.println("顾客拿到门票入场!");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 3; i++) {
                    try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
                    System.out.println("售票处第" + (i + 1) + "小时售出两张票!");
                    // Release two permits each hour
                    semaphore.release();
                    semaphore.release();
                }
            }
        }).start();

        System.out.println("售票处开始售票!");
    }
}

The result shows customers waiting, tickets being released in batches, and customers entering as permits become available, illustrating how Semaphore limits concurrent access.

Exchanger

Exchanger allows two threads to swap data at a synchronization point, similar to a two‑person CyclicBarrier but with an exchange operation.

public class TestExchanger {
    public static void main(String[] args) {
        Exchanger
exchanger = new Exchanger<>();

        new Thread(new Runnable() {
            @Override
            public void run() {
                String weapon = "装备";
                System.out.println("我是卖家,我带着" + weapon + "过来了!");
                try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
                System.out.println("卖家到达交易地点");
                try {
                    System.out.println("我是卖家,换回了" + exchanger.exchange(weapon));
                } catch (InterruptedException e) { e.printStackTrace(); }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                String money = "一万游戏币";
                System.out.println("我是买家,我带着" + money + "过来了");
                try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); }
                System.out.println("买家到达交易地点");
                try {
                    System.out.println("我是买家,换回了" + exchanger.exchange(money));
                } catch (InterruptedException e) { e.printStackTrace(); }
            }
        }).start();
    }
}

The execution shows the seller and buyer arriving at the exchange point, swapping their items, and printing the exchanged values, demonstrating how Exchanger synchronizes and transfers data between two threads.

JavaconcurrencySemaphoreCountDownLatchCyclicBarrierExchanger
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.