CountDownLatch 源码分析
来源:互联网 发布:adobe xd for mac 编辑:程序博客网 时间:2024/06/05 17:38
1. 类介绍
一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。
2. 使用场景
在一些应用场合中,需要等待某个条件达到要求后才能做后面的事情。
CountDownLatch最重要的方法是countDown()和await()两个方法,countDown主要是倒数一次,await是等待倒数到0,如果没有到达0,就只有阻塞等待了。
例如:
A 和 B 相约一起吃饭,等A和B都到指定顶点后才能开始吃饭,下面用代码模拟实现。
示例
public class CountDownLatchTest { static CountDownLatch c = new CountDownLatch(2); public static void main(String[] args) { new Thread(new Runnable() { public void run() { System.out.println("A 我来了"); c.countDown(); } }).start(); new Thread(new Runnable() { public void run() { System.out.println("B 我来了"); c.countDown(); } }).start(); new Thread(new Runnable() { public void run() { try { c.await(); System.out.println("开始吃饭..."); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }}
源码分析:
需要提前了解:AbstractQueuedSynchronizer 源码分析
AQS提供了两种模式:独占模式&共享模式。CountDownLatch就是一个使用共享模式的自定义同步器实现的共享锁。
CountDownLatch 代码不多,主要是通过内部类继承AQS来实现其功能的,下面我们一步一步来分析下源码:
Sync 内部类
private static final class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 4982264981922014374L; //构造Sync对象是初始化AQS中state的数量(共享锁的个数) Sync(int count) { setState(count); } //获取当前state的数量(共享锁个数) int getCount() { return getState(); } //尝试获得获得锁 protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1; } //尝试释放锁 protected 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; } }}
AbstractQueuedSynchronizer 类采用模版模式进行扩展实现其相应的功能。子类只需要实现
如下5个方法就能实现其不同功能的锁。
而CountDownLatch 的内部类Sync使用的是共享锁所以只实现了tryAcquireShared和tryReleaseShared方法。
CountDownLatch的构造方法
public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count);}
创建CountDownLatch对象时,需要传入一个int的计数器。
await 方法
public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1);}public boolean await(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}
await方法调用AQS的获得锁的方法,只有AQS的state状态为0时才能获得锁,如果state不为0,则需要在AQS的等待队列中阻塞等待。
public void countDown() { sync.releaseShared(1);}
countDown方法则调用AQS的releaseShared方法,释放共享锁,也就是每次将state状态每次减一,直到减到0,则唤醒队列中的所有节点(线程)。
public long getCount() { return sync.getCount();}
获取计数器当前值。
本人简书blog地址:http://www.jianshu.com/u/1f0067e24ff8
点击这里快速进入简书
- 《Java源码分析》:CountDownLatch
- JUC - CountDownLatch 源码分析
- 源码分析-CountDownLatch
- CountDownLatch 源码分析
- CountDownLatch源码分析
- 《Java源码分析》:CountDownLatch
- CountDownLatch源码分析
- Java源码分析之CountDownLatch
- Java 并发 --- CountDownLatch源码分析
- JUC源码分析10-locks-CountDownLatch
- Java并发之CountDownLatch源码分析
- 【Java8源码分析】并发包-CountDownLatch
- 根据AQS推测CountDownLatch及源码分析
- CountDownLatch源码
- jdk 源码分析(15)java CountDownLatch 源码解析
- CountDownLatch分析
- 分析countdownlatch
- java多线程Thread join与CountDownLatch源码分析
- GitHub分支(branch)合并
- OpenvSwitch 2.5 代码分析与编译安装
- AngularJS 最常用的八种功能
- robotium获取某一个按钮上的文字
- ActivityOptionsCompat动画的使用
- CountDownLatch 源码分析
- MTK编译笔记1
- 【Python】遍历文件夹中所有文件
- 计算机网络实验ethereal
- C# 线程控制
- Scene(场景)的使用
- Activity#finish() 对其生命周期的影响
- Intellij idea項目中无法创建scala class的解决办法
- OkHttp3的使用