CountDownLatch 和 CyclicBarrier 是 Java 并发编程中两个常用的同步工具类,它们都可以用于协调多个线程之间的执行顺序和状态,都可以理解成维护的就是一个计数器,但是这两者还是各有不同侧重点的:
- CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;CountDownLatch强调一个线程等多个线程完成某件事情。CyclicBarrier是多个线程互等,等大家都完成,再携手共进。
- 调用CountDownLatch的countDown方法后,当前线程并不会阻塞,会继续往下执行;而调用CyclicBarrier的await方法,会阻塞当前线程,直到CyclicBarrier指定的线程全部都到达了指定点的时候,才能继续往下执行;
- CountDownLatch方法比较少,操作比较简单,而CyclicBarrier提供的方法更多,比如能够通过getNumberWaiting(),isBroken()这些方法获取当前多个线程的状态,并且CyclicBarrier的构造方法可以传入barrierAction,指定当所有线程都到达时执行的业务功能;
- CountDownLatch是不能复用的,而CyclicBarrier是可以复用的。
// CountDownLatch 示例
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
int count = 3;
CountDownLatch latch = new CountDownLatch(count);
for (int i = 0; i < count; i++) {
new Thread(() -> {
// 模拟线程执行任务
System.out.println(Thread.currentThread().getName() + " 执行任务");
// 任务完成后计数器减一
latch.countDown();
}).start();
}
// 等待所有线程执行完毕
latch.await();
System.out.println("所有任务执行完毕");
}
}
// CyclicBarrier 示例
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
int count = 3;
CyclicBarrier barrier = new CyclicBarrier(count);
for (int i = 0; i < count; i++) {
new Thread(() -> {
// 模拟线程执行任务
System.out.println(Thread.currentThread().getName() + " 执行任务");
try {
// 线程到达屏障点等待
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
// 屏障打开后执行下一步操作
System.out.println(Thread.currentThread().getName() + " 继续执行任务");
}).start();
}
}
}
以上代码示例中,CountDownLatch 用于等待多个线程执行完毕后再执行主线程的后续操作,而 CyclicBarrier 用于多个线程相互等待,直到所有线程都到达某个屏障点后再同时执行下一步操作。