在讲闭锁之前,我们先来思考一个问题:在多线程环境下,主线程打印一句话,如何保证这句话最后(其他线程全部执行完毕)打印?

博主目前可以想到的实现方式有两种。一种是通过 join() 方法实现,另一种就是用闭锁。如果大家有好的解决办法,可以在下面留言,下面进入正题。

一、什么是闭锁

闭锁(CountDownLatch)是 java.util.concurrent 包下的一种同步工具类。闭锁可以用来确保某些活动直到其他活动都完成后才执行。

闭锁相当于一扇门:在闭锁到达结束状态之前,这扇门一直是关闭的,并且没有任何线程能通过,当达到结束状态时,这扇门会打开,并允许所有的线程通过。

下面是 CountDownLatch 中的方法:

CountDownLatch 中有一个计数器字段,在对象创建时初始化,表示需要等待的事件数量。countDown() 方法递减计数器,表示有一个事件已经发生了,await() 方法等待计数器为 0 时,表示所有的需要等待的时间都已经发生。如果计数器的值非 0 会一直阻塞直到计数器为 0。

下面使用闭锁来实现文章开头的问题:

public class CountDownLatchTest {/*** 初始化需要等待的 3 个事件*/private static CountDownLatch latch = new CountDownLatch(3);public static void main(String[] args) throws InterruptedException {/*** 创建 3 个线程去执行事件*/new Thread(() -> {System.out.println("*****_*****");latch.countDown();}).start();new Thread(() -> {System.out.println("*****_*****");latch.countDown();}).start();new Thread(() -> {System.out.println("*****_*****");latch.countDown();}).start();// 在计数器为 0 之前会一直阻塞latch.await();System.out.println("~~~~~_~~~~~");}
}

执行结果:

二、闭锁的用途

我们已经知道了闭锁的使用方法,但是闭锁都是有哪些应用场景呢?

  • 确保某个计算在其需要的所有资源都被初始化之后才执行
  • 确保某个服务在其依赖的所有其他服务都已经启动之后才启动
  • 等待直到每个操作的所有参与者都就绪再执行(比如打麻将时需要等待四个玩家就绪)

CountDownLatch 底层是基于 AQS(AbstractQueuedSynchronizer)实现的,关于 AQS 的知识会在后续的博文中进行分析,大家有兴趣的可以持续关注。

PS:在一开始提到了使用 join() 方法解决打印问题,下面把代码贴出来供大家参考。

public class ThreadJoinTest {public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> System.out.println("*****_*****"));Thread thread2 = new Thread(() -> System.out.println("*****_*****"));Thread thread3 = new Thread(() -> System.out.println("*****_*****"));thread1.start();thread2.start();thread3.start();/*** 作用:在 A 线程中调用了 B 线程的 join() 方法时,* 表示只有当 B 线程执行完毕时,A 线程才能继续执行* 原理:调用了当前线程的 wait() 方法*/thread1.join();thread2.join();thread3.join();System.out.println("~~~~~_~~~~~");}
}

参考资料

《Java 并发编程实战》

Java 并发编程系列之闭锁(CountDownLatch)相关推荐

  1. Java并发工具类(闭锁CountDownLatch)

    并发工具类系列: Java并发工具类(闭锁CountDownLatch) Java并发工具类(栅栏CyclicBarrier) Java并发工具类(信号量Semaphore) 闭锁是一种同步工具类,可 ...

  2. Java并发编程系列

    Java并发编程系列 2018-03-08 Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) ...

  3. 『死磕Java并发编程系列』并发编程工具类之CountDownLatch

    <死磕 Java 并发编程>系列连载中,大家可以关注一波:

  4. java并发实战编程pdf_「原创」Java并发编程系列25 | 交换器Exchanger

    2020年Java面试题库连载中 [000期]Java最全面试题库思维导图 [001期]JavaSE面试题(一):面向对象 [002期]JavaSE面试题(二):基本数据类型与访问修饰符 [003期] ...

  5. Java并发编程工具类:CountDownLatch、CyclicBarrier、Semaphore

    在jdk5中,java提供了一些非常有用的辅助工具类,包括CountDownLatch和CyclicBarrier(两者都可以实现线程之间的通信).Semaphore(控制方法被线程访问的数量),他们 ...

  6. java闭锁_【Java并发编程三】闭锁

    1.什么是闭锁? 闭锁(latch)是一种Synchronizer(Synchronizer:是一个对象,它根据本身的状态调节线程的控制流.常见类型的Synchronizer包括信号量.关卡和闭锁). ...

  7. Java 并发编程系列之带你了解多线程

    早期的计算机不包含操作系统,它们从头到尾执行一个程序,这个程序可以访问计算机中的所有资源.在这种情况下,每次都只能运行一个程序,对于昂贵的计算机资源来说是一种严重的浪费. 操作系统出现后,计算机可以运 ...

  8. reentrantlock非公平锁不会随机挂起线程?_【原创】Java并发编程系列16 | 公平锁与非公平锁...

    本文为何适原创并发编程系列第 16 篇,文末有本系列文章汇总. 上一篇提到重入锁 ReentrantLock 支持两种锁,公平锁与非公平锁.那么这篇文章就来介绍一下公平锁与非公平锁. 为什么需要公平锁 ...

  9. 『图解Java并发编程系列』10张图告诉你Java并发多线程那些破事

    目录 线程安全问题 活跃性问题 性能问题 有态度的总结 头发很多的程序员:『师父,这个批量处理接口太慢了,有什么办法可以优化?』架构师:『试试使用多线程优化』第二天头发很多的程序员:『师父,我已经使用 ...

最新文章

  1. JAVA-基础(Class对象及反射)
  2. hadoop入门-在windows上安装,测试hadoop
  3. jwt与token+redis,哪种方案更好用?
  4. 中文任务型对话系统中的领域分类
  5. 构建企业服务之Windows Server 2008 DNS 高级部署
  6. 为何亏损还要烧更多的钱?这次何小鹏说清楚了
  7. 自定义拦截器,拦截到了某个请求就返回给前端一个JSON串
  8. mysql的网址是什么意思_Mysql数据库地址是什么怎么填写
  9. 我打算学计算机学英语,英语人教版八年级上册我打算学习计算机科学.doc
  10. 去世父亲在儿子手机中复活,这可能是最温暖的一个AI
  11. WSL Ubuntu忘记root密码和用户密码
  12. 理论分析 | 势流理论与水动力
  13. ZOJ1516HDU1507(二分图匹配)
  14. 计算机无法安装MUMU模拟器,如何解决重装MuMu模拟器时无法更换安装目录
  15. 如何评价深度学习相关顶级期刊论文难复现的问题?
  16. KeyError: 2
  17. sequence_loss_by_example()函数在Tensorflow2.x找不到
  18. 无人驾驶技术入门(八)| 被严重低估的传感器超声波雷达
  19. Arduino笔记实验(初级阶段)—Keypad小键盘
  20. 如何刻录VCD防盗光盘

热门文章

  1. Spring Cloud Gateway——2020.x以上版本HTTP 503 或 NoLoadBalancer[负载均衡]解决方案
  2. 《计算机组成原理》实验报告——TEC-2实验系统——运算器实验
  3. dreamstart的催促
  4. 【笔记】顺序存储结构求二叉树深度
  5. 用Socket 打造跨语言跨操作系统的网络MORPG游戏(三)
  6. Python实训day08pm【面试和职场的经验分享】
  7. spring中容器启动过程中初始化资源使用方法
  8. iOS开发教程:Storyboard全解析-第二部分
  9. JAVA中的异常使用
  10. TCP往返时延的估计和超时