CountDownLatch源码解析

CountDownLatch使用AQS中的共享锁实现
一个或多个线程等待一个或多完成之后再执行
同步值0是中间状态
await方法 同步状态的值大于0线程阻塞
countDown方法 同步状态的值减一 同步状态的值等于0 唤起所有等待的线程

重要构造

它就一个构造方法

    /**
     *  初始化内部属性Sync 同步器 设置同步状态的值
     * @param count 同步状态的值
     */
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

    Sync(int count) {
        setState(count);//设置同步状态的值
    }

    /**
     * 设置state AQS中的属性
     */
    protected final void setState(int newState) {
        state = newState;
    }

重要方法

await


    /**
     * 	尝试获取共享锁可中断对外提供的
     * 	内部同步器实现
     * 	state != 0 阻塞线程
     */
    public void await() throws InterruptedException {
    	//调用AQS中的模板方法
        sync.acquireSharedInterruptibly(1);
    }
    /**
     * 	获取共享锁  可中断
     */
    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
    	//当前线程被标记为中断的 直接抛出异常
        if (Thread.interrupted())
            throw new InterruptedException();
        //尝试获取共享锁 子类实现小于0
        if (tryAcquireShared(arg) < 0)
        	//获取共享锁 AQS实现
            doAcquireSharedInterruptibly(arg);
    }

这个我们已经很熟悉了,是AQS中的模板方法,AQS中的细节我就不说了。
然后我们来看CountDownLatchtryAcquireShared的具体实现,它是怎么样才会阻塞线程的吧。
在这里插入图片描述
可以看到和我们开头说的是一样的,状态值不为0,就会尝试阻塞当前线程,状态值为0了,不会阻塞。

countDown


再来看看与之对立的countDown

    /**
     * 	state减一
     * 	内部同步器实现
     */
    public void countDown() {
    	//调用AQS中的模板方法
        sync.releaseShared(1);
    }

    /**
     * 	释放共享锁
     */
    public final boolean releaseShared(int arg) {
    	//尝试释放共享锁成功 子类实现
        if (tryReleaseShared(arg)) {
            //唤醒后继阻塞节点
        	doReleaseShared();
            return true;
        }
        return false;
    }

重点还是关注CountDownLatchtryReleaseShared的实现,它对释放锁成功是怎么定义的。
在这里插入图片描述
可以看到,当状态值减到0的时候,它才算是释放锁成功,然后会唤醒所有因为调用await而阻塞的线程。

典型应用

某线程等待多个线程执行完毕,然后才开始执行。

	public static void main(String[] args) throws InterruptedException {
		int count = 5 ;
		CountDownLatch countDownLatch = new CountDownLatch(count);
		//线程池 核心线程数 3 最大线程数 5 大于核心线程数的线程空闲存活时间 200毫秒 阻塞队列 LinkedBlockingQueue 无限制的
		ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 5, 200, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
		for (int i = 0; i < count; i++) {
			executor.execute(()->{
				try {
					Thread.sleep(1000);
					System.out.println("执行完成");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				countDownLatch.countDown();
			});
		}
		countDownLatch.await();
		System.out.println("主线程执行完成");
		//停掉线程池
		executor.shutdown();
	}

关于CountDownLatch的完整源码解析点击这里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值