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.
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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.