Understanding Java Concurrency Utilities: CountDownLatch, CyclicBarrier, Semaphore, and Exchanger
This article explains four Java concurrency utilities—CountDownLatch, CyclicBarrier, Semaphore, and Exchanger—detailing their concepts, typical use cases, and providing complete code examples that demonstrate synchronization patterns such as thread coordination, resource limiting, and data exchange.
The author (CoderV) provides a practical tutorial on several Java concurrency utilities, illustrating their purpose, usage patterns, and sample code for multithreaded applications.
CountDownLatch
Explanation
CountDownLatch acts like a gate with N locks; the gate opens only after all N locks are released. It is useful when one thread must wait for several other threads to finish their work before proceeding.
Code
public class TestCountDownLatch {
public static void main(String[] args) {
// Need to wait for two threads, so the count is 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 worker threads finish
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// After both threads finish, main thread continues
System.out.println("裁判发枪,1号选手和2号选手开跑!");
}
}Output
请1号选手和2号选手各就各位!
1号选手准备就绪!用时1秒!
2号选手准备就绪!用时3秒!
裁判发枪,1号选手和2号选手开跑!If the latch is removed, the main thread would fire the "gun" before the worker threads are ready, leading to out‑of‑order execution.
CyclicBarrier
Explanation
CyclicBarrier works like a fence that makes a set of threads wait for each other. Unlike CountDownLatch, each participating thread calls await() and waits for the others; once all have arrived, they are released together and the barrier can be reused.
Code
public class TestCyclicBarrier {
// 1号选手跑的轮数
public static int countA = 1;
// 2号选手跑的轮数
public static int countB = 1;
public static void main(String[] args) {
// 2 threads need to 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++ + "轮比赛!");
// 1号选手跑得慢,每次跑三秒
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
System.out.println("1号选手抵达终点!");
// Wait for the other thread
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++ + "轮比赛!");
// 2号选手跑得快,每次跑一秒
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
System.out.println("2号选手抵达终点!");
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}).start();
}
}Output
1号选手开始跑!当前第1轮比赛!
2号选手开始跑!当前第1轮比赛!
2号选手抵达终点!
1号选手抵达终点!
1号选手开始跑!当前第2轮比赛!
2号选手开始跑!当前第2轮比赛!
2号选手抵达终点!
1号选手抵达终点!
1号选手开始跑!当前第3轮比赛!
2号选手开始跑!当前第3轮比赛!
2号选手抵达终点!
1号选手抵达终点!Without the barrier, the faster thread would finish all rounds before the slower one, breaking the intended coordination.
Semaphore
Explanation
A Semaphore controls access to a limited number of permits. Threads call acquire() to obtain a permit (blocking if none are available) and release() to return it, making it useful for limiting concurrent resource usage.
Code
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() {
for (;;) {
try {
Thread.sleep(500);
// Wait for a 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); // One hour per batch
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("售票处第" + (i + 1) + "小时售出两张票!");
// Release two permits each hour
semaphore.release();
semaphore.release();
}
}
}).start();
System.out.println("售票处开始售票!");
}
}Output
顾客在售票处等候中...
售票处开始售票!
售票处第1小时售出两张票!
顾客拿到门票入场!
顾客拿到门票入场!
售票处第2小时售出两张票!
顾客拿到门票入场!
顾客拿到门票入场!
售票处第3小时售出两张票!
顾客拿到门票入场!
顾客拿到门票入场!Exchanger
Explanation
An Exchanger provides a synchronization point where two threads can exchange data objects. It works like a two‑party CyclicBarrier but adds the ability to swap values between the participating threads.
Code
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();
}
}Output
我是卖家,我带着装备过来了!
我是买家,我带着一万游戏币过来了
卖家达到交易地点
买家到达交易地点
我是买家,换回了装备
我是卖家,换回了一万游戏币These examples demonstrate common synchronization scenarios in Java multithreading, helping developers choose the appropriate utility for thread coordination, resource throttling, and data exchange.
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.