概述
CyclicBarrier
和 CountDownLatch
是 Java 中用于线程同步的两个并发工具。虽然这两个类都用于协调线程,但它们有不同的目的和用法。
CyclicBarrier
CyclicBarrier
是一个可重复使用的同步点,允许一组线程等待直到所有线程都到达该点。一旦所有线程都到达该点,屏障就会解除,所有线程都可以继续执行。
CountDownLatch
CountDownLatch
是一个一次性同步点,允许一个或多个线程等待直到一个计数器达到零。一旦计数器达到零,所有等待的线程都可以继续执行。
主要区别
- 可重复使用性:
CyclicBarrier
是可重复使用的,这意味着它可以在线程到达屏障后重置并再次使用。CountDownLatch
是不可重复使用的,一旦计数器达到零,它就完成了。 - 等待条件:
CyclicBarrier
等待所有线程到达屏障。CountDownLatch
等待计数器达到零。 - 线程唤醒:
CyclicBarrier
一次唤醒所有等待的线程。CountDownLatch
逐个唤醒等待的线程。
示例
以下示例演示了 CyclicBarrier
和 CountDownLatch
之间的区别:
CyclicBarrier
public class CyclicBarrierExample {
public static void main(String[] args) {
// 创建一个具有 3 个参与者的 CyclicBarrier
CyclicBarrier barrier = new CyclicBarrier(3);
// 创建 3 个线程
Thread t1 = new Thread(() -> {
try {
// 线程 1 到达屏障
barrier.await();
System.out.println("线程 1 已到达屏障。");
} catch (Exception e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
// 线程 2 到达屏障
barrier.await();
System.out.println("线程 2 已到达屏障。");
} catch (Exception e) {
e.printStackTrace();
}
});
Thread t3 = new Thread(() -> {
try {
// 线程 3 到达屏障
barrier.await();
System.out.println("线程 3 已到达屏障。");
} catch (Exception e) {
e.printStackTrace();
}
});
// 启动线程
t1.start();
t2.start();
t3.start();
}
}
输出:
线程 1 已到达屏障。
线程 2 已到达屏障。
线程 3 已到达屏障。
在这个示例中,三个线程都到达屏障后,屏障解除,所有线程继续执行。
CountDownLatch
public class CountDownLatchExample {
public static void main(String[] args) {
// 创建一个具有 3 个计数的 CountDownLatch
CountDownLatch latch = new CountDownLatch(3);
// 创建 3 个线程
Thread t1 = new Thread(() -> {
try {
// 线程 1 完成任务
latch.countDown();
System.out.println("线程 1 已完成任务。");
} catch (Exception e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
// 线程 2 完成任务
latch.countDown();
System.out.println("线程 2 已完成任务。");
} catch (Exception e) {
e.printStackTrace();
}
});
Thread t3 = new Thread(() -> {
try {
// 线程 3 完成任务
latch.countDown();
System.out.println("线程 3 已完成任务。");
} catch (Exception e) {
e.printStackTrace();
}
});
// 启动线程
t1.start();
t2.start();
t3.start();
// 等待所有线程完成任务
try {
latch.await();
System.out.println("所有线程已完成任务。");
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出:
线程 1 已完成任务。
线程 2 已完成任务。
线程 3 已完成任务。
所有线程已完成任务。
在这个示例中,三个线程完成任务后,计数器达到零,所有等待的线程继续执行。
总结
CyclicBarrier
和 CountDownLatch
都是有用的并发工具,用于协调线程。CyclicBarrier
用于同步一组线程,直到它们都到达一个点,而 CountDownLatch
用于同步一个或多个线程,直到一个计数器达到零。选择哪一个工具取决于任务的需要。