Java并发编程之CountDownLatch介绍及使用场景
温馨提示:
本文最后更新于 2024年05月15日,已超过 252 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我。
介绍
CountDownLatch
是Java中一个非常有用的并发工具类,它能够帮助我们实现多线程间的协调和同步。
在并发编程中,我们经常会遇到这样的场景:一个线程执行某个逻辑依赖于其它一个或多个线程的执行结果,且根据结果不同而执行不同的分支逻辑,这就需要一种机制来实现线程之间的等待和通知。CountDownLatch
就是为了满足这样的需求而设计的工具类之一,它提供了一种机制,它可以让一个或多个线程等待其它线程的结果而执行后续逻辑。
原理
CountDownLatch
是AbstractQueuedSynchronizer
的一个简单扩展。AbstractQueuedSynchronizer
是一个实现先进先出(FIFO
)阻塞队列的基础框架。CountDownLatch
利用该框架内部维护了一个共享计数器及阻塞队列,该计数器初始化时需设置一个正整数,标明需要等待的线程数量。每个线程在完成任务时都会调用countDown()
方法来减小该计数器的值。当计数器的值变为0
时,等待的线程就会被唤醒,继续执行后续的逻辑。
用法
CountDownLatch的主要方法有两个:countDown()
和await()
。
countDown()
: 当线程完成了自己的任务后,调用该方法使用CAS
来减小共享计数器state
的值,当值变为0时唤醒阻塞队列内等待线程执行任务await()
: 调用线程会进入阻塞队列等待共享计数器state
的值变为0时被唤醒执行自身任务
使用场景
CountDownLatch在实际应用中有着广泛的用途,例如:
- N个小伙伴聚餐,当N个人都到达才开始点餐
- A线程逻辑依赖于其它N个子线程结果,根据结果不同执行不同分支
- A线程完成逻辑(比如初始化资源),唤醒其它等待线程同时开始执行
......
示例
public class CountDownLatchDemo {
final static Logger logger = LoggerFactory.getLogger(CountDownLatchDemo.class);
private static final CountDownLatch latch = new CountDownLatch(3);
private static final List<Boolean> LIST = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 3; i++) {
Thread thread = new Thread(() -> {
try {
logger.info("{} 线程模拟任务执行", Thread.currentThread().getName());
LIST.add(Math.random() < 0.5);
} finally {
logger.info("{} 线程执行任务完成,计数器减1", Thread.currentThread().getName());
latch.countDown();
}
});
thread.setName("工作线程" + i);
thread.start();
}
latch.await();
int count = 0;
for (Boolean result : LIST) {
if (result){
count++;
}
}
logger.info("{} 个线程完成了任务,主线程执行逻辑...", count);
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 3; i++) {
Thread thread = new Thread(() -> {
try {
logger.info("{} 正赶往餐厅", Thread.currentThread().getName());
Thread.sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
logger.info("{} 到达餐厅,计数器减1", Thread.currentThread().getName());
latch.countDown();
}
});
thread.setName("伙伴" + i);
thread.start();
}
latch.await();
logger.info("小伙伴都到达,开始点菜...");
}
public static void main(String[] args) {
CountDownLatch startSignal = new CountDownLatch(1);
for (int i = 0; i < 3; i++) {
Thread thread = new Thread(() -> {
try {
startSignal.await();
logger.info("{} 线程开始执行任务", Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.setName("子线程" + i);
thread.start();
}
logger.info("主线程开始执行任务");
logger.info("主线程初始化资源");
startSignal.countDown();
}
总结
CountDownLatch是Java中一个强大的并发工具类,通过它我们可以轻松实现多线程之间的同步。本文介绍了CountDownLatch的原理、用法以及常见的应用场景,希望能够帮助读者更好地理解和使用该工具类。
正文到此结束
- 本文标签: java 并发编程 多线程
- 本文链接: https://www.58cto.cn/article/54
- 版权声明: 本文由程序言原创发布, 非商业性可自由转载、引用,但需署名作者且注明文章出处:程序言 》 Java并发编程之CountDownLatch介绍及使用场景 - https://www.58cto.cn/article/54