我们先看并发编程中提供的几个常用的工具类
CountDownLatch位于java.util.cucurrent包下,Java1.5被引入。同时被引入的还有其他几个工具类比如: CyclicBarrier、Semaphore、ConcurrenthashMap和BlockingQueue等。
CountDownLatch 是一个同步计数器, 通常用于一个线程或者多个线程等待另外一组线程执行完成之前一直等待。
CountDownLatch在使用时,会初始化一个计数器,计数器的数量为线程的数量。 每一个线程执行完成以后,就会调用countDown()方法将计数器的个数-1 ,直到计数器的个为0 , 表示所有线程都执行完毕, 这个时候调用await()方法的等待线程就可以恢复继续工作了。
可以看出 CountDownLatch是基于Sync类实现的,而Sync继承AQS, 是AQS共享模式
举个例子,我们打算200个并发同时去做一笔业务,我们如果使用代码该如何实现呢?
那简单呀,老哥。
我打算去模拟200并发去做业务,那我们知道CountDownLatch 是 等countDown() 逐个减一以后,直到为0, 调用await()的线程才去工作。
那我就模拟让这200个线程调用await() ,然后等 count=0的时候 一起搞业务呗。
MMP,让我想了公司到饭点,大家一起冲刺去干饭的场景 , 这个CountDownLatch 就是那墙壁上的钟表啊 ,滴答滴答 ,就等11:45分…
来吧,show code
package com.artisan.juc;
import java.util.concurrent.CountDownLatch;
/**
* @author 小工匠
* @version 1.0
* @description: TODO
* @date 2021/11/5 1:42
* @mark: show me the code , change the world
*/
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
int cnt = 10;
CountDownLatch countDownLatch = new CountDownLatch(cnt);
// 模拟10个并发干饭
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
// 干饭人准备完毕……干饭人都阻塞在这,等待号令(cnt=0)
countDownLatch.await();
System.out.println("编号:" + Thread.currentThread().getName() + " 开始干饭...." + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 模拟一部分业务耗时
Thread.sleep(10);
// 每个线程调用一次,cnt每次减一,直到为0,就是干饭信号
countDownLatch.countDown();
System.out.println("countDown执行一次,个数:" + (--cnt));
}
}
}
可以看到,我们通过CountDownLatch#await()
方法,让多个业务线程启动后阻塞等待, 等待主线程调用CountDownLatch#count()
方法将计数器减为0以后,让所有的业务线程一起并发运行,这样就实现了我们多个线程并发的目的。
举个例子,我们有一些依赖关系的业务
String str = method1(); // 耗时1S
String str2 = method2();// 耗时2S
method3(str, str2);
这mmp ,数据有依赖呀, 当然了,你可以用CompletableFuture
优化,我们这里不讨论它嘛
我们看看CountDownLacth
该怎么玩?
分析一下这个业务场景, 让method 1 和 method 2 异步执行,然后执行完以后再回到主线程,取到返回结果汇总呗
我们简化下,不获取返回结果
package com.artisan.juc;
import java.util.concurrent.*;
/**
* @author 小工匠
* @version 1.0
* @description: TODO
* @date 2021/11/5 1:42
* @mark: show me the code , change the world
*/
public class CountDownLatchTest2 {
public static void main(String[] args) throws InterruptedException {
// 2 为线程个数
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(1);
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName() + " --执行结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(2);
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName() + "**执行结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
countDownLatch.await();
System.out.println("主线业务继续执行");
}
}
我们可以看到: 在每个线程 完成的最后一行加上CountDownLatch#countDown()
,让计数器-1;当所有线程完成-1,主线程之前阻塞在这里 countDownLatch.await();
,直到计数器减到0后,往下继续执行自己的业务。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有