
📫作者简介:小明Java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于知名金融公司后端高级工程师。
🏆 2022博客之星TOP3 | CSDN博客专家 | 后端领域优质创作者 | CSDN内容合伙人
🏆 InfoQ(极客邦)签约作者、阿里云专家 | 签约博主、51CTO专家 | TOP红人、华为云享专家
🔥如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主~
🍅 文末获取联系 🍅 👇🏻 精彩专栏推荐订阅收藏 👇🏻
专栏系列(点击解锁)
学习路线(点击解锁)
知识定位
🔥Redis从入门到精通与实战🔥
Redis从入门到精通与实战
围绕原理源码讲解Redis面试知识点与实战
🔥MySQL从入门到精通🔥
MySQL从入门到精通
全面讲解MySQL知识与企业级MySQL实战 🔥计算机底层原理🔥
深入理解计算机系统CSAPP
以深入理解计算机系统为基石,构件计算机体系和计算机思维
Linux内核源码解析
围绕Linux内核讲解计算机底层原理与并发
🔥数据结构与企业题库精讲🔥
数据结构与企业题库精讲
结合工作经验深入浅出,适合各层次,笔试面试算法题精讲
🔥互联网架构分析与实战🔥
企业系统架构分析实践与落地
行业最前沿视角,专注于技术架构升级路线、架构实践
互联网企业防资损实践
互联网金融公司的防资损方法论、代码与实践
🔥Java全栈白宝书🔥
精通Java8与函数式编程
本专栏以实战为基础,逐步深入Java8以及未来的编程模式
深入理解JVM
详细介绍内存区域、字节码、方法底层,类加载和GC等知识
深入理解高并发编程
深入Liunx内核、汇编、C++全方位理解并发编程
Spring源码分析
Spring核心七IOC/AOP等源码分析
MyBatis源码分析
MyBatis核心源码分析
Java核心技术
只讲Java核心技术
本文目录
本文导读
一、什么是CountDownLatch
二、CountDownLatch实现原理
1、CountDownLatch数据结构
2、countDown() 方法
3、await() 方法
总结
本文导读
本文讲解什么是CountDownLatch,CountDownLatch的特点以及使用场景,对CountDownLatch的数据结构与countDown()方法、await()方法源码进行剖析。
一、什么是CountDownLatch
CountDownLatch可以使线程顺序执行
CountDownLatch 类在创建实例的时候,需在构造函数中传入倒数次数,然后由需要等待的线程去调用 await 方法开始等待,而每一次其他线程调用了 countDown 方法之后,计数便会减 1,直到减为 0 时,之前等待的线程便会继续运行。
CountDownLatch 不能重用,可以考虑使用 CyclicBarrier 或者创建一个新的 CountDownLatch 实例。
1、CountDownLatch可以让一个线程等待其他多个线程都执行完毕,再继续自己的工作
public static void main(String[] args) throws InterruptedException {
	CountDownLatch latch = new CountDownLatch(5);
	ExecutorService service = Executors.newFixedThreadPool(5);
	for (int i = 0; i < 5; i++) {
		final int no = i + 1;
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				latch.countDown();
			}
		};
		service.submit(runnable);
	}
	latch.await();
	System.out.println("所有线程都执行完");
} 
2、多个线程等待某一个线程的信号,同时开始执行
public static void main(String[] args) throws InterruptedException {
	CountDownLatch countDownLatch = new CountDownLatch(1);
	ExecutorService service = Executors.newFixedThreadPool(5);
	for (int i = 0; i < 5; i++) {
		final int no = i + 1;
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				countDownLatch.await();
			}
		};
		service.submit(runnable);
	}
	System.out.println("执行开始!");
	countDownLatch.countDown();
} 
二、CountDownLatch实现原理
1、CountDownLatch数据结构
CountDownLatch是利用AQS共享锁机制的同步器Sync来实现的
public class CountDownLatch {
    // 继承AQS来实现同步器,
    private static final class Sync extends AbstractQueuedSynchronizer {
	
		// 通过state控制count
        Sync(int count) {
            setState(count);
        }
		// 重写AQS的tryAcquireShared,通过获取共享锁的方式实现等待
        protected int tryAcquireShared(int acquires) {
			// 当state不为0时一直阻塞
            return (getState() == 0) ? 1 : -1;
        }
		// 释放共享锁
        protected boolean tryReleaseShared(int releases) {
            for (;;) {
                int c = getState();
				
				// 如果state为0,则不能再使用,
                if (c == 0) return false;
				// state减1
                int nextc = c-1;
				// 为0,释放共享锁,唤醒等待线程
                if (compareAndSetState(c, nextc)) return nextc == 0;
            }
        }
    }
	// 同步器变量
    private final Sync sync;
    // 创建同步器,设置AQS的state变量为1
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }
} 
2、countDown() 方法
// 直接调用AQS的releaseShared,释放共享锁,从而回调tryAcquireShared
public void countDown() {
    sync.releaseShared(1);
} 
3、await() 方法
public void await() throws InterruptedException {
    // 调用AQSacquireSharedInterruptibly,释放共享锁
    sync.acquireSharedInterruptibly(1);
} 
总结
本文讲解什么是CountDownLatch,CountDownLatch的特点以及使用场景,对CountDownLatch的数据结构与countDown()方法、await()方法源码进行剖析。



















