当前位置: 首页 > news >正文

详解CountDownlatch

引言

CountDownLatch 是 Java 并发包 java.util.concurrent 中的一个同步工具类,由著名的并发编程大师 Doug Lea 所开发。它允许一个或多个线程等待其他线程完成操作后再继续执行,其核心思想是通过一个计数器,对计数器进行调度来实现

原理

CountDownLatch 初始化时会设置一个计数器的值,该值表示需要等待完成的操作数量。每当一个线程完成了自己的任务后,会调用 countDown() 方法将计数器减 1。当计数器的值变为 0 时,意味着所有需要等待的操作都已完成,此时在 await() 方法上等待的线程将被唤醒,继续执行后续操作。

源码分析

内部类

private final Sync sync;

private static final class Sync extends AbstractQueuedSynchronizer {
    private static final long serialVersionUID = 4982264981922014374L;

    Sync(int count) {
        setState(count);
    }

    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;
        }
    }
}
  • sync:CountDownLatch 内部使用 Sync 类的实例,Sync 继自 AbstractQueuedSynchronizer(AQS),借助 AQS 的状态(state)来表示计数器的值。
  • Sync 类:
    • 构造函数 Sync(int count):在创建 Sync 实例时,会调用 setState(count) 方法将 AQS 的状态初始化为传入的计数器值。
    • getCount() 方法:返回 AQS 的当前状态,即计数器的当前值。
    • tryAcquireShared(int acquires) 方法:用于尝试以共享模式获取锁。当计数器值为 0 时返回 1,表示可以获取锁;否则返回 -1,表示无法获取锁。
    • tryReleaseShared(int releases) 方法:用于尝试以共享模式释放锁。使用 for(;;) 无限循环结合 compareAndSetState 方法(CAS 操作)来安全地将计数器减 1。当计数器减为 0 时返回 true,表示释放成功且可以唤醒等待线程;否则返回 false。

结合源码我们一般是主线程设计为等待线程,线程池去完成计数器的增减

内部方法

await()

public void await() throws InterruptedException {
    sync.acquireSharedInterruptibly(1);
}
  • await() 方法会调用 sync 的 acquireSharedInterruptibly(1) 方法,该方法是 AQS 提供的以共享模式获取锁的可中断方法。其具体逻辑为:
    • 检查当前线程是否被中断,若被中断则抛出 InterruptedException 异常。

    • 调用 tryAcquireShared 方法尝试获取锁,若计数器为 0 则获取成功,线程继续执行;否则将当前线程放入等待队列并阻塞。

await(long timeout, TimeUnit unit) 

public boolean await(long timeout, TimeUnit unit)
    throws InterruptedException {
    return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}

该方法允许线程等待指定的时间。调用 sync 的 tryAcquireSharedNanos(1, unit.toNanos(timeout)) 方法,在指定时间内尝试以共享模式获取锁。若在超时时间内计数器变为 0 则返回 true;若超时则返回 false。

countDown() 

countDown() 方法调用 sync 的 releaseShared(1) 方法,以共享模式释放锁。该方法会调用 tryReleaseShared 方法尝试将计数器减 1,若减为 0 则唤醒所有在等待队列中的线程。

实战

下面是多线程实战CountDownlatch,依旧是主线程等待,在循环中创建线程调用await方法

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个 CountDownLatch 实例,计数器初始值为 3
        CountDownLatch latch = new CountDownLatch(3);

        // 创建并启动三个工作线程
        for (int i = 0; i < 3; i++) {
            final int workerId = i;
            new Thread(() -> {
                try {
                    System.out.println("Worker " + workerId + " is working.");
                    // 模拟工作
                    Thread.sleep((long) (Math.random() * 1000));
                    System.out.println("Worker " + workerId + " has finished.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 工作完成,计数器减 1
                    latch.countDown();
                }
            }).start();
        }

        // 主线程等待所有工作线程完成
        System.out.println("Main thread is waiting for workers to finish.");
        latch.await();
        System.out.println("All workers have finished. Main thread can continue.");
    }
}

相关文章:

  • MaxKB + Ollama + DeepSeek本地部署
  • 输入网址到网页显示,发生了什么?
  • 人工智能框架:连接理论与实践的桥梁
  • VAS1260IB05E 集成内部开关驱动器的汽车级LED硬灯带高效解决方案
  • Gentleman:优雅的Go语言HTTP客户端工具包
  • 【GESP】2024年12月图形化一级 -- 火箭回收
  • Anchor-Based 与 Anchor-Free
  • 通过VSCode直接连接使用 GPT的编程助手
  • python003-python电影数据分析及可视化系统建设(源码+数据库+部署讲解等)
  • iOS开发书籍推荐 - 《高性能 iOS应用开发》(附带链接)
  • 深度求索-DeepSeek-R1本地部署指南
  • UART(一)——UART基础
  • 遥感影像目标检测:从CNN(Faster-RCNN)到Transformer(DETR)
  • 第3章 .NETCore核心基础组件:3.1 .NET Core依赖注入
  • 申论对策建议类【2022江苏B卷第一题“如何开展网络直播”】
  • OpenCV图像基本操作
  • 期权帮|股指期货的有效止盈止损策略?
  • Unsloth
  • 软件定义汽车时代的功能安全和信息安全
  • 【MySQL】第六弹---数据库表约束详解:从空属性到主键的全方位指南
  • 做网站gzip压缩/长春seo排名
  • 小学生做网站/软文广告有哪些
  • 南宁微网站开发/昆明seo博客
  • 广东省住房和城乡建设局网站首页/如何让自己的网站快速被百度收录
  • 北京网站建设哪个好/2024年瘟疫大爆发
  • 亦庄网站开发公司/东莞seo托管