Java并发教程– CountDownLatch
其他实用程序不太常见,因此有时它们可能会使我们逃脱,但是请记住它们是很好的。 CountDownLatch是这些工具之一。
CountDownLatch –更通用的等待/通知机制
各种Java开发人员都应该熟悉等待/通知方法,直到达到条件为止。 以下是有关其工作原理的一些示例:
public void testWaitNotify() throws Exception {final Object mutex = new Object();Thread t = new Thread() {public void run() {// we must acquire the lock before waiting to be notifiedsynchronized(mutex) {System.out.println("Going to wait " +"(lock held by " + Thread.currentThread().getName() + ")");try {mutex.wait(); // this will release the lock to be notified (optional timeout can be supplied)} catch (InterruptedException e) {e.printStackTrace();} System.out.println("Done waiting " +"(lock held by " + Thread.currentThread().getName() + ")");}}};t.start(); // start her up and let her wait()// not normally how we do things, but good enough for demonstration purposesThread.sleep(1000);// we acquire the lock released by wait(), and notify()synchronized (mutex) {System.out.println("Going to notify " +"(lock held by " + Thread.currentThread().getName() + ")");mutex.notify();System.out.println("Done notify " +"(lock held by " + Thread.currentThread().getName() + ")");}}
输出量
Going to wait (lock held by Thread-0)
Going to notify (lock held by main)
Done notify (lock held by main)
Done waiting (lock held by Thread-0)
实际上, CountDownLatch可以类似于等待/通知,仅使用一个通知即可使用-也就是说,只要您不希望在获取锁并调用wait()之前调用notify()时, wait()就会停顿。 。 因此,它实际上是更宽容的,在某些情况下,这正是您想要的。 这是一个示例:
public void testWaitNotify() throws Exception {final CountDownLatch latch = new CountDownLatch(1); // just one timeThread t = new Thread() {public void run() {// no lock to acquire!System.out.println("Going to count down...");latch.countDown();}};t.start(); // start her up and let her wait()System.out.println("Going to await...");latch.await();System.out.println("Done waiting!");
}
如您所见,它比等待/通知更简单,并且所需的代码更少。 它还允许我们在调用wait()之前调用最终释放该块的条件。 这可能意味着代码更安全。
真实的例子
因此我们知道我们可以将其用作更简单的等待/通知机制,但是您可能已经在上面看到了构造函数参数。 在构造函数中,指定解锁之前需要递减锁存器的次数。 有什么可能的用途? 好吧,它可以使进程等待直到采取了一定数量的动作。
例如,如果您具有可以通过侦听器或类似方法挂接到的异步进程,则可以创建单元测试以验证是否进行了一定数量的调用。 这使我们只需要在正常情况下需要的时间(或在保释并假设失败之前的某个限制)即可。
最近,我遇到了一种情况,我必须验证是否已将JMS消息从队列中拉出并正确处理。 这自然是异步的,并且不在我的控制范围之内,并且也不选择模拟,因为它是具有Spring上下文的完全组装的应用程序,等等。为了测试这一点,我对使用服务进行了微小的更改,以允许在邮件已处理。 然后,我可以临时添加一个侦听器,该侦听器使用CountDownLatch保持测试尽可能接近同步。
这是显示概念的示例:
public void testSomeProcessing() throws Exception {// should be called twicefinal CountDownLatch testLatch = new CountDownLatch(2);ExecutorService executor = Executors.newFixedThreadPool(1);AsyncProcessor processor = new AsyncProcessor(new Observer() {// this observer would be the analogue for a listener in your async processpublic void update(Observable o, Object arg) {System.out.println("Counting down...");testLatch.countDown();}});//submit two tasks to be process// (in my real world example, these were JMS messages)executor.submit(processor);executor.submit(processor);System.out.println("Submitted tasks. Time to wait...");long time = System.currentTimeMillis();testLatch.await(5000, TimeUnit.MILLISECONDS); // bail after a reasonable timelong totalTime = System.currentTimeMillis() - time;System.out.println("I awaited for " + totalTime +"ms. Did latch count down? " + (testLatch.getCount() == 0));executor.shutdown();
}// just a process that takes a random amount of time
// (up to 2 seconds) and calls its listener
public class AsyncProcessor implements Callable<Object> {private Observer listener;private AsyncProcessor(Observer listener) {this.listener = listener;}public Object call() throws Exception {// some processing here which can take all kinds of time...int sleepTime = new Random().nextInt(2000);System.out.println("Sleeping for " + sleepTime + "ms");Thread.sleep(sleepTime);listener.update(null, null); // not standard usage, but good for a demoreturn null;}
}
输出量
Submitted tasks. Time to wait...
Sleeping for 739ms
Counting down...
Sleeping for 1742ms
Counting down...
I awaited for 2481ms. Did latch count down? true
结论
CountDownLatch就是这样。 它不是一个复杂的主题,而且用途有限,但是当您遇到类似我的问题时,很高兴看到示例并知道它们在您的工具箱中。 将来,如果没有其他问题,我一定会牢记这一点,以便进行更简单的等待/通知。 如果您对此帖子或系列中的其他帖子有疑问或评论,请留言。
参考:来自Carfey Software博客的 JCG合作伙伴的Java并发第6部分– CountDownLatch 。
- Java并发教程–信号量
- Java并发教程–重入锁
- Java并发教程–线程池
- Java并发教程–可调用,将来
- Java并发教程–阻塞队列
- Exchanger和无GC的Java
- Java Fork / Join进行并行编程
- 使用迭代器时如何避免ConcurrentModificationException
- 改善Java应用程序性能的快速技巧
翻译自: https://www.javacodegeeks.com/2011/09/java-concurrency-tutorial.html
Java并发教程– CountDownLatch相关推荐
- Java并发教程–阻塞队列
如第3部分所述,Java 1.5中引入的线程池提供了核心支持,该支持很快成为许多Java开发人员的最爱. 在内部,这些实现巧妙地利用了Java 1.5中引入的另一种并发功能-阻塞队列. 队列 首先,简 ...
- Java并发教程–可调用,将来
从Java的第一个发行版开始,Java的美丽之处之一就是我们可以轻松编写多线程程序并将异步处理引入我们的设计中. Thread类和Runnable接口与Java的内存管理模型结合使用,意味着可以进行简 ...
- Java并发教程–重入锁
Java的synced关键字是一个很棒的工具–它使我们能够以一种简单可靠的方式来同步对关键部分的访问,而且也不难理解. 但是有时我们需要对同步进行更多控制. 我们要么需要分别控制访问类型(读取和写入) ...
- Java并发教程–信号量
这是我们将要进行的Java并发系列的第一部分. 具体来说,我们将深入探讨Java 1.5及更高版本中内置的并发工具. 我们假设您对同步和易失性关键字有基本的了解. 第一篇文章将介绍信号量-特别是对信号 ...
- Java并发教程–线程池
Java 1.5中提供的最通用的并发增强功能之一是引入了可自定义的线程池. 这些线程池使您可以对诸如线程数,线程重用,调度和线程构造之类的东西进行大量控制. 让我们回顾一下. 首先,线程池. 让我们直 ...
- java并发中CountDownLatch的使用
文章目录 主线程等待子线程全都结束之后再开始运行 等待所有线程都准备好再一起执行 停止CountdownLatch的await java并发中CountDownLatch的使用 在java并发中,控制 ...
- java并发初探CountDownLatch
java并发初探CountDownLatch CountDownLatch是同步工具类能够允许一个或者多个线程等待直到其他线程完成操作. 当前前程A调用CountDownLatch的await方法进入 ...
- Java并发教程(Oracle官方资料)
2019独角兽企业重金招聘Python工程师标准>>> 本文是Oracle官方的Java并发相关的教程,感谢并发编程网的翻译和投递. (关注ITeye官微,随时随地查看最新开发资讯. ...
- oracle java 并发_【转】JAVA并发教程(ORACLE官网资料)
本文是Oracle官方的Java并发相关的教程,感谢并发编程网的翻译和投递. 计算机的使用者一直以为他们的计算机可以同时做很多事情.他们认为当其他的应用程序在下载文件,管理打印队列或者缓冲音频的时候他 ...
最新文章
- Android Studio-设置鼠标悬停显示方法声明
- OpenCV3图像处理——霍夫曼变换直线检测
- 超赞的 PyTorch 资源大列表,有人把它翻译成了中文版!
- unity怎么实现人脸追踪_景区人脸识别解决方案 人脸识别过闸机怎么实现
- 3.1.6 OS之分页存储(页号、页偏移量等)
- linux启动lighttpd服务,如何使用Yum在CentOS和RHEL上安装Lighttpd Web服务器
- datagrid出现相同两组数据_多数据库联用挖掘肝细胞癌症的血管侵犯特征基因
- 使用 Azure Container Registry 储存镜像
- 图书馆管理系统项目思路
- 大型网站技术架构(八)--网站的安全架构(转)
- 最详细的Extmail安装文档
- C64x+ 与 C64x Cache 区别
- 电机驱动芯片效果对比
- POJ3658Matrix( 双重二分+负数+死循环)
- android 遥控器home键键值,android 中遥控器键值的添加和修改
- 微信小程序发布上线流程
- 利用IDEA的远程debug进行远程代码调试。
- pink老师 js p85思考题
- 挺住,意味着一切--读书笔记
- DRA成国家标准 音视频步入中国时代
热门文章
- 让CentOS能用yum自动安装rar和unrar
- jvm(2)-OutOfMemoryError 异常(内存溢出异常)
- mybatis多表新增如何获取主键ID
- 使用静态代理模式实现公用的报表导出功能
- java锁_Java锁
- 容器rocker_用Rocker制作模板
- esb 和 开源esb_如果今天完成,ESB会是什么样子?
- 什么时候需要使用cqrs_在CQRS读取模型中使用Hibernate进行快速开发
- apache karaf_未来是Apache Karaf上的微服务架构
- SSL Kafka经纪人从Kafka Mirror Maker迁移到Brooklin的挑战