CountDownLatch(闭锁/门阀)是一个同步协助类,允许一个或多个线程等待,直到其他线程完成 操作集。
1、CountDownLatch使用给定的计数值(count)初始化
2、await阻塞等待
3、countDown方法count--
方法
| // 调用 await() 方法的线程会被挂起,等待直到 count 值为 0 才继续执行 public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } // 每调用一次countDown()方法,count值就会-1,当count值为0时,调用线程就能通过await()方法,恢复执行自己的任务 public void countDown() { }; |
await是阻塞,countDown是倒计,构造函数中指定初始值。只有初始值被countDown到0时,阻塞才会被打开,所有等待的线程都会被释放。 count不会被重置(一次性现象). 这是和CyclicBarrier最大的区别。
主线程等待子线程都执行完才能执行。
- package runnable;
-
- import java.util.concurrent.CountDownLatch;
- import java.util.concurrent.LinkedBlockingQueue;
- import java.util.concurrent.ThreadPoolExecutor;
- import java.util.concurrent.TimeUnit;
-
- /**
- * ClassName CountDownLatchTest
- * description CountDownLatchTest
- *
- * @author : HMF
- * date: 2022/7/29 15:42
- **/
-
- public class CountDownLatchTest {
- public static void main(String[] args){
- int RUNNER_COUNT=5;
- CountDownLatch latch = new CountDownLatch(RUNNER_COUNT);
- ThreadPoolExecutor exs=new ThreadPoolExecutor(5,10,0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue
()); - for (int i=0;i
- exs.execute(new Runnable01(latch));
- }
- exs.shutdown();
- try {
- latch.await(); //必须等待计数器count等于0,等于0之后,主线程执行
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("主线程执行");
- }
- static class Runnable01 implements Runnable{
- private CountDownLatch latch;
- public Runnable01(CountDownLatch latch){
- this.latch=latch;
- }
- @Override
- public void run() {
- System.out.println("子线程执行,线程名称:"+Thread.currentThread().getName());
- latch.countDown(); //计数器count-1
- }
- }
- }
执行结果:

3.3、CyclicBarrier和CountDownLatch区别
1、CountDownLatch的await()线程会等待计数器减为0,而执行CyclicBarrier的await()方法会使线程进入阻塞等待其他线程到达障点。
2、CountDownLatch计数器不能重置,CyclicBarrier可以重置循环利用。
3、CountDownLatch是基于AQS的共享模式实现的,CyclicBarrier是基于ReentrantLock和Condition实现的。
一个是利用AQS获取status值,另一种是通过ReentrantLock的唤醒机制来实现。
备注:
CountDownLatch侧重于一个或者多个线程等待其他线程中执行的操作完成。应用场景如:背景想要获取用户最大的数据集合(用户基本数据、订单、购物车信息),但是用户基本数据、订单、购物车信息都在不同的微服务中,这种情况可以使用,主线程在获取基本数据的同时,将订单信息、购物信息另开线程异步获取,最终主线程会等待其他线程获取的消息进行合集返回。(例如老师等待学生考完试后收试卷,适合任务A执行完后再执行任务B)
CyclicBarrier更加侧重:所有的线程都在await()的,等待最后一个计数之后,所有的线程统一执行。(例如:栅栏拦住跑者,等待所有人(线程)到达后一起去跑(执行),适合压测)
CountDownLatch来说,重点是“一个线程等待(多个线程)”,而其他的N个线程在完成“某件事情”之后,可以终止,也可以等待。而对于CyclicBarrier,重点是多个线程,在任意一个线程没有完成,所有的线程都必须互相等待,然后继续一起执行。
参考:https://www.jianshu.com/p/3c6315b4923b
https://www.jianshu.com/p/d593dea9172d