CountDownLatch 和 CyclicBarrier 的区别
CountDownLatch 和 CyclicBarrier 的区别
1、面试官: 现在我有50个任务,这50个任务在完成之后,才能执行下一个「函数」,要是你,你怎么设计?
候选者:可以用JDK给我们提供的线程工具类,CountDownLatch 和 CyclicBarrier 都可以完成这个需求。这两个类都可以等到线程完成之后,才去执行某些操作。
2、面试官:那既然都能实现的话?那 CountDownLatch 和 CyclicBarrier 有什么什么区别呢?
候选者:主要的区别就是CountDownLatch用完了,就结束了,没法复用。而CyclicBarrier不一样,它可以复用。这两者的等待主体是不一样的。CountDownLatch调用await()通常是主线程/调用线程,而CyclicBarrier调用await()是在任务线程调用的。并且这两个类都是基于AQS实现的。
3、面试官:其实我在问 CountDownLatch 和 CyclicBarrier 有什么什么区别的时候,你就可以围绕源码可以给我讲讲。而不是随便说CountDownLatch是一次性的,而CyclicBarrier可在完成时重置进而重复使用就来敷衍我。
候选者:比如说CountDownLatch你就可以回答:前面提到了CountDownLatch也是基于AQS实现的,它的实现机制很简单,当我们在构建CountDownLatch对象时,传入的值其实就会赋值给 AQS 的关键变量state,执行countDown方法时,其实就是利用CAS 将state 减一。执行await方法时,其实就是判断state是否为0,不为0则加入到队列中,将该线程阻塞掉(除了头结点)。
回到CyclicBarrier上,代码也不难,重点就是await方法。从源码不难发现的是,它没有像CountDownLatch和ReentrantLock使用AQS的state变量,而CyclicBarrier是直接借助ReentrantLock加上Condition 等待唤醒的功能 进而实现的。在构建CyclicBarrier时,传入的值会赋值给CyclicBarrier内部维护count变量,也会赋值给parties变量(这是可以复用的关键),每次调用await时,会将count -1 ,操作count值是直接使用ReentrantLock来保证线程安全性。如果count不为0,则添加到condition队列中,如果count等于0时,则把节点从condition队列添加至AQS的队列中进行全部唤醒,并且将parties的值重新赋值为count的值(实现复用)。
4、再简单总结下:
CountDownlatch基于AQS实现,会将构造CountDownLatch的入参传递至state,countDown()就是在利用CAS将state减-1,await()实际就是让头节点一直在等待state为0时,释放所有等待的线程
而CyclicBarrier则利用ReentrantLock和Condition,自身维护了count和parties变量。每次调用await将count-1,并将线程加入到condition队列上。等到count为0时,则将condition队列的节点移交至AQS队列,并全部释放。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
2020-05-28 Elasticsearch简介