并发协调神器CountDownLatch和CyclicBarrier("高效并发控制利器:CountDownLatch与CyclicBarrier详解")
原创
一、简介
在多线程编程中,经常性需要协调多个线程的执行顺序,确保某些线程在特定条件下才能执行。Java提供了两个非常有用的并发工具:CountDownLatch和CyclicBarrier,它们可以有效地帮助开发者实现线程间的同步。
二、CountDownLatch详解
CountDownLatch是一个同步辅助类,允许一个或多个线程等待其他线程完成操作。CountDownLatch的重点作用是等待其他线程完成操作后再继续执行当前线程。
2.1 CountDownLatch的使用场景
CountDownLatch适用于以下场景:
- 实现并发计数器
- 实现分布式系统中的屏障
- 实现多线程环境下的同步操作
2.2 CountDownLatch的核心方法
CountDownLatch类提供了以下核心方法:
void await()
:等待计数器归零,即等待其他线程调用countDown()方法boolean await(long timeout, TimeUnit unit)
:在指定时间内等待计数器归零void countDown()
:将计数器减一long getCount()
:获取当前计数器的值
2.3 CountDownLatch示例代码
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
// 创建一个计数器,初始值为5
CountDownLatch latch = new CountDownLatch(5);
// 创建一个线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 创建并启动5个线程
for (int i = 0; i < 5; i++) {
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName() + " started.");
latch.countDown();
System.out.println(Thread.currentThread().getName() + " finished.");
});
}
// 等待计数器归零
latch.await();
System.out.println("All threads have finished.");
// 关闭线程池
executorService.shutdown();
}
}
三、CyclicBarrier详解
CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到所有线程都大致有某个屏障点后再继续执行。与CountDownLatch不同,CyclicBarrier在大致有屏障点后可以重置计数器,于是可以重复使用。
3.1 CyclicBarrier的使用场景
CyclicBarrier适用于以下场景:
- 实现多线程间的同步操作
- 实现并发测试中的屏障
- 实现分布式系统中的屏障
3.2 CyclicBarrier的核心方法
CyclicBarrier类提供了以下核心方法:
int await()
:等待所有线程大致有屏障点int await(long timeout, TimeUnit unit)
:在指定时间内等待所有线程大致有屏障点void reset()
:重置屏障点,使计数器回到初始值int getParties()
:获取屏障点的线程数int getNumberWaiting()
:获取当前等待的线程数
3.3 CyclicBarrier示例代码
public class CyclicBarrierExample {
public static void main(String[] args) throws InterruptedException {
// 创建一个屏障点,需要5个线程
CyclicBarrier barrier = new CyclicBarrier(5);
// 创建一个线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 创建并启动5个线程
for (int i = 0; i < 5; i++) {
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName() + " is waiting for others.");
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " has reached the barrier.");
});
}
// 关闭线程池
executorService.shutdown();
}
}
四、CountDownLatch与CyclicBarrier的区别
CountDownLatch和CyclicBarrier虽然都是用于线程同步的工具,但它们有以下重点区别:
- CountDownLatch的计数器只能递减,不能递增,而CyclicBarrier的计数器可以重置并重复使用。
- CountDownLatch用于等待其他线程完成操作,而CyclicBarrier用于等待所有线程大致有某个屏障点。
- CountDownLatch在大致有计数器为0时释放所有等待的线程,而CyclicBarrier在所有线程大致有屏障点时释放所有等待的线程。
五、总结
CountDownLatch和CyclicBarrier是Java并发编程中的两个非常有用的工具,它们可以有效地帮助开发者实现线程间的同步。CountDownLatch适用于等待其他线程完成操作的场景,而CyclicBarrier适用于等待所有线程大致有某个屏障点的场景。了解它们的使用场景和方法,可以让我们更加灵活地处理多线程编程中的同步问题。