博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java并发编程-CountDownLatch
阅读量:6968 次
发布时间:2019-06-27

本文共 3329 字,大约阅读时间需要 11 分钟。

hot3.png

1、 应用场景

  CountDownLatch是并发包中用来控制一个或者多个线程等待其他线程完成操作的并发工具类。现以工作中的一个场景来描述下CountDownLatch的应用,代码如下:

 

/*模拟工作中的一个需求场景:用户会选择多个算法来计算费用,最后会将所有算法计算出的费用做一个加权求平均数,这个平均数是最终的费用。每个算法的复杂度都不一样,打算每个线程负责一个算法的实现,所有的线程执行完成,最后再求平均数。1、为每个算法创建一个线程,每个线程负责一个算法的实现2、通过CountDownLatch来控制所有算法线程的同步3、全部计算完成后再求平均数 */public class CountDownLatchTask {    public static void main(String[] args) {        CountDownLatchTask countDownLatchTask = new CountDownLatchTask();        countDownLatchTask.startThreads(5);    }    //根据线程数和选择的算法 调度算法对应的实现    private void startThreads(int threadNumber) {        CountDownLatch countDownLatch = new CountDownLatch(threadNumber);        for (int i = 0; i < threadNumber; i++) {            new Thread(new Runnable() {                @Override                public void run() {                    System.out.println("线程算法实现:" + Thread.currentThread().getName());                    countDownLatch.countDown();                }            }).start();        }        try {            countDownLatch.await();            System.out.println("加权求平均数");        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

 

  在分析原理实现前,总结下CountDownLatch的作用就是阻塞其他线程直到条件允许后才释放该阻塞,除了上述这个小案例,实际工作中还有很多可以使用CountDownLatch的场景,比如解析Excel文件时可以同时解析多个Sheet页,所有的Sheet解析完成才算完成了Excel文件的解析。从这个代码中也可以看到CountDownLatch的主要方法就是await和countDown,下面将以这两个方法来分析下CountDownLatch的原理实现。

 2、 源码原理解析

 2.1 await方法

  调用await方法会阻塞当前线程直到计数器的数值为0,方法如下:

public void await() throws InterruptedException {        sync.acquireSharedInterruptibly(1); //共享式获取AQS的同步状态}

  调用的是AQS的acquireSharedInterruptibly方法:

 

public final void acquireSharedInterruptibly(int arg)            throws InterruptedException {        if (Thread.interrupted())//线程中断 说明闭锁对线程中断敏感            throw new InterruptedException();        if (tryAcquireShared(arg) < 0) //闭锁未使用完成 线程进入同步队列自旋等待             doAcquireSharedInterruptibly(arg);    }

 

  其中tryAcquireShared依赖的是Sync的实现,和之前的、及相比,CountDownLatch的Sync只提供了一种方式,代码如下:

protected int tryAcquireShared(int acquires) {            return (getState() == 0) ? 1 : -1; //AQS的同步状态为0则闭锁结束 可以进行下一步操作        }

  doAcquireSharedInterruptibly方法就不再赘述,和之前的实现是一致的,本质上仍然是AQS同步队列的入队自旋等待。

2.2 countDown方法

  调用countDown方法会将计数器的数值减1直到计数器为0,方法如下:

public void countDown() {        sync.releaseShared(1);    }

  和一样,调用的是AQS的releaseShared方法:

 

public final boolean releaseShared(int arg) {        if (tryReleaseShared(arg)) {//减少闭锁的计数器            doReleaseShared();//唤醒后续线程节点           return true;        }        return false;    }

 

  其中tryReleaseShared依赖的是Sync的实现,和之前的、及相比,CountDownLatch的Sync只提供了一种方式,代码如下:

 

protected boolean tryReleaseShared(int releases) {            // Decrement count; signal when transition to zero            for (;;) {                int c = getState();                if (c == 0)                    return false; //计数器已经是0了                int nextc = c-1; //计数器减1                if (compareAndSetState(c, nextc)) //CAS更新同步状态                    return nextc == 0;                    加群:874811168 一起学习,一起进步                    进群即可免费领取资料一份            }        }

 

  唤醒后续线程节点的doReleaseShared也不再赘述,和之前的实现是一致的。

  总结:CountDownLatch类使用AQS同步状态来表示计数。在await时,所有的线程进入同步队列自旋等待,在countDown时,获取闭锁成功的线程会减少闭锁的计数器,同时唤醒后续线程取获取闭锁,直到await中的计数器为0,获取到闭锁的线程才可以通过,执行下一步操作。

        出处:https://www.cnblogs.com/iou123lg/p/9739697.html

转载于:https://my.oschina.net/u/3971241/blog/2222704

你可能感兴趣的文章
Android逆向从未如此简单
查看>>
从Android Studio 开始的ARCore之旅
查看>>
Android轮播图控件CustomBanner的使用讲解
查看>>
让你在服务器上顺风顺水——linux常用命令
查看>>
[iOS] [OC] NSNotificationCenter 进阶及自定义(附源代码)
查看>>
Python logging 库的『完整教程』
查看>>
springboot -- 2.0版本自定义ReidsCacheManager的改变
查看>>
应用层,了解一下
查看>>
Failed to execute aapt
查看>>
创建个人cocopods集合(仅供参考)
查看>>
OAuth2.0认证授权workflow探究
查看>>
《Android Security Internals》第二章权限翻译
查看>>
笔者介绍
查看>>
spring-cloud Sleuth
查看>>
大数据成神之路
查看>>
重新梳理下js中的深拷贝和浅拷贝
查看>>
个推Node.js 微服务实践:基于容器的一站式命令行工具链
查看>>
Taro 多端开发的正确姿势:打造三端统一的网易严选(小程序、H5、React Native)...
查看>>
105. Construct Binary Tree from Preorder and Inorder Traversal
查看>>
Data Lake Analytics: 以SQL方式查询Redis数据
查看>>