一、引入案例
假如说有6个同学在教室上自习(模拟6个线程),班长(主线程)拿着教室的钥匙,等到下课后,必须等所有的同学都离开了,班长才能锁门离开。如何实现?
普通的实现:
private static void closeDoor() {
for (int i = 0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 离开教室");
}, String.valueOf(i)).start();
}
System.out.println(Thread.currentThread().getName() + "\t 班长锁门离开了");
}
上面这种情况下,不知道哪个线程会先执行,只要抢占到 CPU 就可以执行了。
二、CountDownLatch 减少计数
CountDownLatch 类可以设置一个计数器,然后通过 countDown 方法来进行减 1 的操作,使用 await 方法等待计数器不大于 0,然后继续执行 await 方法之后的语句。
CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,这些线程会阻塞。
其它线程调用 countDown 方法会将计数器减 1(调用 countDown 方法的线程不会阻塞)。
当计数器的值变为 0 时,因 await 方法阻塞的线程会被唤醒,继续执行。
三、案例:6 个同学陆续离开教室后值班同学才可以关门
代码实现:
public class CountDownLatchDemo {
//6 个同学陆续离开教室后值班同学才可以关门
public static void main(String[] args) throws InterruptedException {
//定义一个数值为 6 的计数器
CountDownLatch countDownLatch = new CountDownLatch(6);
//创建6个同学
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+" 号同学离开了教室");
//计数器 -1,不会阻塞
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
//主线程 await 休息
System.out.println("主线程睡觉");
countDownLatch.await();
//全部离开后自动唤醒主线程
System.out.println(Thread.currentThread().getName()+" 班长锁门走人了");
System.out.println("全部离开了,现在的计数器为" + countDownLatch.getCount());
}
}
让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒。
main主线程必须要等前面6个线程完成全部工作后,自己才能开干。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
2021-01-23 第三节:装饰者模式在JDK中的应用
2021-01-23 第二节:装饰者模式—定义与应用
2021-01-23 第一节:装饰者设计模式-需求分析与传统实现