什么是CountDownLatch

成都创新互联长期为近1000家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为龙海企业提供专业的成都网站设计、做网站,龙海网站改版等技术服务。拥有10多年丰富建站经验和众多成功案例,为您定制开发。
CountDownLatch是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就减1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上(调用await方法的线程)等待的线程就可以恢复工作了。
应用场景
CountDownLatch可以用来干什么呢?有什么应用场景?实际项目中有应用的场景吗?这应该才是大家比较关心的。我们先来看看官网提供的例子是如何进行应用的https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html 官方提供了两个demo我直接把它转成了图片顺带推荐下这个代码转图片的网址https://www.dute.org/code-snapshot 还挺好用的。
官网demo1
The first is a start signal that prevents any worker from proceeding until the driver is ready for them to proceed; The second is a completion signal that allows the driver to wait until all workers have completed.”
官网demo2
Another typical usage would be to divide a problem into N parts, describe each part with a Runnable that executes that portion and counts down on the latch, and queue all the Runnables to an Executor. When all sub-parts are complete, the coordinating thread will be able to pass through await.”
另一种典型的用法就是把一个大任务拆分N个部分,让多个线程(Worker)执行,每个线程(Worker)执行完自己的部分计数器就减1,当所有子部分都完成后,Driver 才继续向下执行才继续执行。就好比富士康手机加工的流水线一样,组装一步手机需要一条条的流水线来相互配合完成。一条条流水线(Worker),每条线都干自己的活。有的流水线是贴膜的,有的流水线是打螺丝的,有的流水线是质检的、有的流水线充电的、有的流水线贴膜的。等这些流水线都干完了就把一部手机组装完成了。
上面两个就是官方提供的demo,下面我再来两个我们平时开发中可以用到的栗子:
多个线程等待:模拟并发,让并发线程一起执行。
有时候我们写了接口想去压测下它,看看它的最大并发数大概是多少。当然我们可以使用Jmeter来进行压测,但是有时候我们不想去下载工具,其实就可以借助CountDownLatch来实现。
- /**
 - * @author: 公众号:java金融
 - */
 - public class TestCountDownLatch1 {
 - public static void main(String[] args) throws InterruptedException {
 - CountDownLatch countDownLatch = new CountDownLatch(1);
 - for (int i = 0; i < 5; i++) {
 - new Thread(() -> {
 - try {
 - //所有请求都阻塞在这,等待
 - countDownLatch.await();
 - // 调用测试接口
 - System.out.println(Thread.currentThread().getName() + "开始执行……");
 - } catch (InterruptedException e) {
 - e.printStackTrace();
 - }
 - }).start();
 - }
 - // 让请求都准备好
 - Thread.sleep(2000);
 - // 让所有请求统一请求
 - countDownLatch.countDown();
 - }
 - }
 
我们通过CountDownLatch.await(),让多个参与者线程启动后阻塞等待,然后在主线程 调用CountDownLatch.countdown() 将计数减为0,让所有线程一起往下执行;以此实现了多个线程在同一时刻并发执行,来模拟并发请求的目的。
单个线程等待:多个线程(任务)完成后,进行汇总合并
- /**
 - * @author: 公众号:java金融
 - */
 - public class TestCountDownLatch1 {
 - public static void main(String[] args) throws InterruptedException {
 - int count = 3;
 - CountDownLatch countDownLatch = new CountDownLatch(count);
 - for (int i = 0; i < count; i++) {
 - final int index = i;
 - new Thread(() -> {
 - try {
 - Thread.sleep(1000 + ThreadLocalRandom.current().nextInt(1000));
 - System.out.println("finish" + index + Thread.currentThread().getName());
 - } catch (InterruptedException e) {
 - e.printStackTrace();
 - }finally{
 - countDownLatch.countDown();
 - }
 - }).start();
 - }
 - countDownLatch.await();// 主线程在阻塞,当计数器==0,就唤醒主线程往下执行。
 - System.out.println("主线程:在所有任务运行完成后,进行结果汇总");
 - }
 - }
 
这种场景应该是用的最多了,比如我们打开一个电商的个人中心页面,我们需要调用,用户信息接口、用户订单接口、用户会员信息等接口,然后合并后一起给到前端,假设每个接口最长耗时为1s,如果我们同步调用的话最大耗时时间是3s,如果我们采用异步调用然后合并结果,所以最大的耗时时间是3s。每个接口调用返回数据后调用countDown方法,让计数器进行减1,当把计数器减为0时的这个线程会去唤醒主线程,让它继续往下走。
CountDownLatch 实现原理
CountDownLatch是通过AQS的state字段来实现的一个计数器,计数器的初始值(state的值)为new CountDownLatch设置的数量,每次调用countDown的时候,state的值会进行减1,最后某个线程将state值减为0时,会把调用了await()进行阻塞等待的线程进行唤醒。CountDownLatch重写了tryReleaseShared这个方法,只有当state这个字段被设置为0时,也就是tryReleaseShared返回true的情况就会执行doReleaseShared方法,把调用了await的线程进行唤醒。
- public final boolean releaseShared(int arg) {
 - if (tryReleaseShared(arg)) {
 - doReleaseShared();
 - return true;
 - }
 - return false;
 - }
 - rotected boolean tryReleaseShared(int releases) {
 - // Decrement count; signal when transition to zero
 - for (;;) {
 - int c = getState();
 - if (c == 0)
 - return false;
 - int nextc = c-1;
 - if (compareAndSetState(c, nextc))
 - return nextc == 0;
 - }
 - }
 
CountDownLatch的其他源码就不进行分析了, 相信看了这两篇文章《Java高并发编程基础之AQS》、《Java高并发编程基础三大利器之Semaphore》再来看这个还是比较轻松的。
总结
本文转载自微信公众号「java金融」,可以通过以下二维码关注。转载本文请联系java金融公众号。
                分享标题:Java高并发编程基础三大利器之CountDownLatch
                
                URL链接:http://www.csdahua.cn/qtweb/news30/249030.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网