CountDownLatch源码解读
程序员文章站
2022-06-14 10:26:32
...
一、什么是CountDownLanch?
给定一个指定数量的计数器,调用指定方法(countDown)计数器减一,调用指定方法(await)来等待计数归0,后面被阻塞的代码得以执行
CountDownLatch(int count) //创建一个倒计数器,指定计数个数count
countDown() // 计数减一
await() //等待,当计数减到0时,所有线程并行执行
下面是一个使用例子
public class CountDownDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownDemo =new CountDownLatch(10);
for (int i= 0; i< 9;i++){
new Thread(() -> {
System.out.println(Thread.currentThread()+"我准备好了!");
countDownDemo.countDown();
try {
countDownDemo.await(); //等待计数器为0 不为0 不执行 后面的
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("我是:"+Thread.currentThread()+"我执行了接口"+"调用了");
}).start();
}
//等待2秒 最后的线程才启动
Thread.sleep(2000L);
new Thread(() -> {
countDownDemo.countDown();
}).start();
System.out.println("我是最后一个线程 是时候表演真正的技术啦!!");
}
}
执行结果如图:
二、源码分析
public class CountDownLatch {
//继承AQS来实现他的模板方法(tryAcquireShared,tryReleaseShared)
private static final class Sync extends AbstractQueuedSynchronizer {
//计数个数Count
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
//AQS方法getState(),返回同步状态,这里指计数器值
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
//循环+cas重试 直到计数器为0 跳出,则release(实现aqs共享模式释放方法)
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;
}
}
}
private final Sync sync;
//实例化
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//带有一个超时时间的awit
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
public void countDown() {
sync.releaseShared(1);
}
public long getCount() {
return sync.getCount();
}
}
三、总结
CountDownLatch和信号量Semaphore一样都是共享模式下资源问题,这些源码实现AQS的模板方法,然后使用CAS+循环重试实现自己的功能。在RT多个资源调用,或者执行某种操作依赖其他操作完成下可以发挥这个计数器的作用。
上一篇: LinkedHashMap源码解读
下一篇: Spring Bean的生命周期
推荐阅读
-
spring5 源码深度解析-----ApplicationContext容器refresh过程
-
解读针灸解痛原理与效果
-
Android开发中总结的Adapter工具类【附完整源码下载】
-
解读:华为方舟编译器的革命性到底体现在哪里?
-
解读真正的赵氏孤儿,赵氏孤儿真的是“正义”的一方吗?
-
jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】
-
并发编程(二)—— CountDownLatch、CyclicBarrier和Semaphore
-
netty源码解解析(4.0)-23 ByteBuf内存管理:分配和释放
-
区块链专家、中国银行原行长李礼辉解读区块链(分布式智库精选)
-
松鼠AI创始人栗浩洋亮相哈佛中国教育论坛 解读AI+教育新趋势