CountDownLatch 简单用法-记录

参考+引用:https://www.cnblogs.com/liun1994/p/7396026.html

CountDownLatch 是java1.5 之后在java.util.concurrent包下引入的并发类

CountDownLatch能等待其他线程执行完毕后再执行自己线程,CountDownLatch是JDK 5+里面闭锁的一个实现。

闭锁(latch):是一种同步方法,就像一个大门一样,门没打开之前,所有的线程都被阻断,门一打开,则所有的线程都通过,该门的状态也无法改变,所以闭锁是一次性的。

        与CountDownLatch第一次交互是主线程等待其它的线程,主线程必须在启动其它线程后立即调用await方法,这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。

  其他的N个线程必须引用闭锁对象,因为他们需要通知CountDownLatch对象,他们已经完成了各自的任务,这种机制就是通过countDown()方法来完成的。每调用一次这个方法,在构造函数中初始化的count值就减1,所以当N个线程都调用了这个方法count的值等于0,然后主线程就能通过await方法,恢复自己的任务。

  这里的主线程是相对的概念,需要根据CountDownLatch创建的场景分析。

例子:

两个工人干活,活干完之后通知主线程,让主线程进行结算工钱...

代码:

import java.util.concurrent.CountDownLatch;

public class Worker implements Runnable {

    private String name;

    private CountDownLatch latch;

    public Worker(String name , CountDownLatch latch){
        this.name = name;
        this.latch = latch;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(3000);

            System.out.println( this.name + "事情干完了" );
            this.latch.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 两个线程,两个线程工作完毕之后,才唤醒主线程
        CountDownLatch countDownLatch = new CountDownLatch(2);

        Worker w1 = new Worker("zhangsan",countDownLatch);
        Worker w2 = new Worker("lisi",countDownLatch);

        w1.start();
        w2.start();

        countDownLatch.await();
        System.out.println("工人工作完成了...结算工钱...");
    }

}

 

### Java 中使用 `CountDownLatch` 模拟并发场景 以下是基于 `CountDownLatch` 实现的一个简单示例,用于模拟并发场景。此代码展示了如何利用 `CountDownLatch` 来协调多个线程的操作。 #### 代码实现 ```java import java.util.concurrent.CountDownLatch; public class CountDownLatchExample { public static void main(String[] args) throws InterruptedException { int threadCount = 5; // 定义参与的线程数量 CountDownLatch startSignal = new CountDownLatch(1); // 控制所有线程同时启动 CountDownLatch doneSignal = new CountDownLatch(threadCount); // 记录已完成的任务数 for (int i = 0; i < threadCount; ++i) { // 创建并启动多个工作线程 new Thread(new Worker(startSignal, doneSignal)).start(); } System.out.println("主线程通知子线程开始..."); startSignal.countDown(); // 主线程发出信号,让所有子线程开始运行 System.out.println("等待所有子线程完成任务..."); doneSignal.await(); // 主线程等待所有子线程完成任务 System.out.println("所有子线程已全部完成!"); } } class Worker implements Runnable { private final CountDownLatch startSignal; private final CountDownLatch doneSignal; public Worker(CountDownLatch startSignal, CountDownLatch doneSignal) { this.startSignal = startSignal; this.doneSignal = doneSignal; } @Override public void run() { try { startSignal.await(); // 等待主线程的通知 System.out.println(Thread.currentThread().getName() + " 正在处理任务..."); simulateWorkload(); // 模拟耗时任务 System.out.println(Thread.currentThread().getName() + " 已完成任务."); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { doneSignal.countDown(); // 告知主线程当前线程已经完成 } } private void simulateWorkload() throws InterruptedException { Thread.sleep((long) (Math.random() * 1000)); // 随机延迟时间,模拟实际工作负载 } } ``` --- #### 关键点解析 1. **初始化计数器** 在上述代码中,定义了一个 `CountDownLatch` 对象 `doneSignal`,其初始值设置为线程总数(即 `threadCount`)。每当一个线程完成任务后,都会调用 `countDown()` 方法减少计数值[^3]。 2. **控制线程启动时机** 使用另一个 `CountDownLatch` 对象 `startSignal`,它的初始值设为 1。这样可以确保所有的子线程都处于等待状态,直到主线程调用了 `countDown()` 才能真正开始执行逻辑[^4]。 3. **等待所有线程完成** 主线程通过调用 `doneSignal.await()` 进入阻塞状态,只有当所有子线程均完成了自己的任务并将计数器降为零之后,主线程才会继续向下执行。 4. **随机化任务执行时间** 子线程中的 `simulateWorkload()` 方法引入了随机化的延时操作,以便更真实地反映不同线程可能具有不同的任务复杂度和执行时间[^5]。 --- #### 输出样例 假设程序中有五个线程,则可能得到如下输出: ``` 主线程通知子线程开始... Thread-0 正在处理任务... Thread-1 正在处理任务... Thread-2 正在处理任务... Thread-3 正在处理任务... Thread-4 正在处理任务... Thread-2 已完成任务. Thread-0 已完成任务. Thread-1 已完成任务. Thread-3 已完成任务. Thread-4 已完成任务. 等待所有子线程完成任务... 所有子线程已全部完成! ``` --- ###
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值