Java中CountDownLatch怎么用

发布时间:2021-11-24 17:39:56 作者:小新
来源:亿速云 阅读:150

Java中CountDownLatch怎么用

1. 概述

在并发编程中,CountDownLatch 是一个非常有用的同步工具类。它允许一个或多个线程等待其他线程完成操作后再继续执行。CountDownLatch 通过一个计数器来实现同步,计数器的初始值通常设置为需要等待的线程数量。每当一个线程完成了自己的任务后,计数器就会减一。当计数器减到零时,等待的线程就会被唤醒,继续执行。

2. CountDownLatch 的基本用法

2.1 创建 CountDownLatch

CountDownLatch 的构造函数接受一个整数参数,表示计数器的初始值。例如:

CountDownLatch latch = new CountDownLatch(3);

这里创建了一个初始值为 3 的 CountDownLatch,表示需要等待 3 个线程完成任务。

2.2 等待其他线程完成任务

主线程可以通过调用 await() 方法来等待其他线程完成任务。await() 方法会阻塞当前线程,直到计数器的值减到零。

latch.await();

2.3 完成任务后减少计数器

每个线程在完成任务后,可以通过调用 countDown() 方法来减少计数器的值。每次调用 countDown() 方法,计数器的值都会减一。

latch.countDown();

2.4 示例代码

下面是一个简单的示例,展示了如何使用 CountDownLatch 来同步多个线程:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {

    public static void main(String[] args) throws InterruptedException {
        int numThreads = 3;
        CountDownLatch latch = new CountDownLatch(numThreads);

        for (int i = 0; i < numThreads; i++) {
            new Thread(new Worker(latch)).start();
        }

        // 主线程等待所有子线程完成任务
        latch.await();
        System.out.println("所有线程已完成任务,主线程继续执行");
    }

    static class Worker implements Runnable {
        private final CountDownLatch latch;

        Worker(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + " 正在执行任务");
                Thread.sleep(1000); // 模拟任务执行时间
                System.out.println(Thread.currentThread().getName() + " 任务完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                latch.countDown(); // 任务完成后减少计数器
            }
        }
    }
}

在这个示例中,主线程创建了 3 个子线程,并使用 CountDownLatch 来等待这些子线程完成任务。每个子线程在完成任务后都会调用 countDown() 方法,减少计数器的值。当计数器的值减到零时,主线程就会被唤醒,继续执行。

3. CountDownLatch 的常见应用场景

3.1 多线程任务的同步

CountDownLatch 最常见的应用场景是多线程任务的同步。例如,在一个多线程任务中,主线程需要等待所有子线程完成任务后再继续执行。这种情况下,可以使用 CountDownLatch 来实现同步。

3.2 并行任务的启动

在某些情况下,我们可能需要同时启动多个线程来执行并行任务。使用 CountDownLatch 可以确保所有线程都准备好后再同时启动。

import java.util.concurrent.CountDownLatch;

public class ParallelTaskStartExample {

    public static void main(String[] args) throws InterruptedException {
        int numThreads = 3;
        CountDownLatch startSignal = new CountDownLatch(1);
        CountDownLatch doneSignal = new CountDownLatch(numThreads);

        for (int i = 0; i < numThreads; i++) {
            new Thread(new Worker(startSignal, doneSignal)).start();
        }

        System.out.println("所有线程已准备就绪,准备同时启动");
        startSignal.countDown(); // 启动所有线程

        doneSignal.await(); // 等待所有线程完成任务
        System.out.println("所有线程已完成任务");
    }

    static class Worker implements Runnable {
        private final CountDownLatch startSignal;
        private final CountDownLatch doneSignal;

        Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
            this.startSignal = startSignal;
            this.doneSignal = doneSignal;
        }

        @Override
        public void run() {
            try {
                startSignal.await(); // 等待启动信号
                System.out.println(Thread.currentThread().getName() + " 正在执行任务");
                Thread.sleep(1000); // 模拟任务执行时间
                System.out.println(Thread.currentThread().getName() + " 任务完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                doneSignal.countDown(); // 任务完成后减少计数器
            }
        }
    }
}

在这个示例中,主线程使用 startSignal 来同时启动所有子线程,并使用 doneSignal 来等待所有子线程完成任务。

3.3 多阶段任务的同步

在某些复杂的多线程任务中,任务可能分为多个阶段。每个阶段的任务完成后,才能进入下一个阶段。这种情况下,可以使用多个 CountDownLatch 来实现多阶段任务的同步。

import java.util.concurrent.CountDownLatch;

public class MultiPhaseTaskExample {

    public static void main(String[] args) throws InterruptedException {
        int numThreads = 3;
        CountDownLatch phase1Latch = new CountDownLatch(numThreads);
        CountDownLatch phase2Latch = new CountDownLatch(numThreads);

        for (int i = 0; i < numThreads; i++) {
            new Thread(new Worker(phase1Latch, phase2Latch)).start();
        }

        phase1Latch.await(); // 等待所有线程完成第一阶段任务
        System.out.println("所有线程已完成第一阶段任务,准备进入第二阶段");

        phase2Latch.await(); // 等待所有线程完成第二阶段任务
        System.out.println("所有线程已完成第二阶段任务");
    }

    static class Worker implements Runnable {
        private final CountDownLatch phase1Latch;
        private final CountDownLatch phase2Latch;

        Worker(CountDownLatch phase1Latch, CountDownLatch phase2Latch) {
            this.phase1Latch = phase1Latch;
            this.phase2Latch = phase2Latch;
        }

        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + " 正在执行第一阶段任务");
                Thread.sleep(1000); // 模拟第一阶段任务执行时间
                System.out.println(Thread.currentThread().getName() + " 第一阶段任务完成");
                phase1Latch.countDown(); // 第一阶段任务完成后减少计数器

                System.out.println(Thread.currentThread().getName() + " 正在执行第二阶段任务");
                Thread.sleep(1000); // 模拟第二阶段任务执行时间
                System.out.println(Thread.currentThread().getName() + " 第二阶段任务完成");
                phase2Latch.countDown(); // 第二阶段任务完成后减少计数器
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这个示例中,主线程使用 phase1Latchphase2Latch 来分别等待所有子线程完成第一阶段和第二阶段的任务。

4. CountDownLatch 的注意事项

4.1 计数器的不可重置性

CountDownLatch 的计数器一旦减到零,就不能再重置。如果需要重复使用计数器,可以考虑使用 CyclicBarrier

4.2 线程中断

如果主线程在等待 CountDownLatch 时被中断,await() 方法会抛出 InterruptedException。因此,在使用 CountDownLatch 时,需要妥善处理线程中断的情况。

4.3 任务完成后的清理工作

在使用 CountDownLatch 时,确保每个线程在完成任务后都会调用 countDown() 方法。如果某个线程没有调用 countDown() 方法,主线程将一直处于等待状态,导致程序无法继续执行。

5. 总结

CountDownLatch 是 Java 并发编程中一个非常有用的工具类,它可以帮助我们实现多线程任务的同步。通过合理地使用 CountDownLatch,我们可以确保主线程在所有子线程完成任务后再继续执行,从而实现复杂的并发控制逻辑。在实际开发中,CountDownLatch 常用于多线程任务的同步、并行任务的启动以及多阶段任务的同步等场景。

推荐阅读:
  1. java中CountDownLatch和CyclicBarrier有什么区别
  2. Java中CountDownLatch的原理是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java countdownlatch

上一篇:如何理解Ribbon中的ServerList

下一篇:如何进行vue入门环境搭建及运行

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》