自学内容网 自学内容网

倒计数器CountDownLatch

CountDownLatch介绍

CountDownLatch是Java并发编程中一个非常实用的同步工具类,它位于java.util.concurrent包下,是JDK 1.5以后加入的。CountDownLatch通过一个计数器来控制多个线程的执行顺序,允许一个或多个线程等待其他线程完成操作后再继续执行。

CountDownLatch的主要方法

  • 构造函数CountDownLatch(int count),传入一个参数count,表示计数器的初始值。

  • await():调用该方法的线程会阻塞,直到计数器值减至0。

  • await(long timeout, TimeUnit unit):与await()方法类似,但增加了超时时间,如果超时则不再等待。

  • countDown():将计数器的值减1,如果计数器的值变为0,则唤醒所有因调用await()方法而阻塞的线程。

经典应用场景

  • 应用启动时的初始化

    在应用程序启动时,可能需要等待多个初始化任务完成(如数据库连接、配置加载等)后,才允许处理客户端请求。此时,可以使用CountDownLatch来等待所有初始化任务完成。

  • 并行任务的同步

    当一个任务需要等待多个并行执行的任务全部完成才能继续时,可以使用CountDownLatch。例如,在并行计算中,将大任务拆分成多个子任务,等待所有子任务完成后,再进行汇总处理。

  • 测试高并发场景

    在模拟高并发测试时,可以控制多个线程同时开始执行,以测试系统在高负载下的表现。通过CountDownLatch,可以确保所有线程同时开始执行。

具体代码示例

使用CountDownLatch的示例,展示了如何让主线程等待若干个子线程全部完成后再继续执行:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchDemo {
    public static int threadCount = 5;
    public static ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
    public static CountDownLatch latch = new CountDownLatch(threadCount);

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < threadCount; ++i) {
            executorService.execute(new WorkerThread());
        }
        latch.await(); // 主线程在此等待,直到计数器变为0
        System.out.println("所有子线程执行完成,主线程继续执行");
        executorService.shutdown();
    }

    static class WorkerThread implements Runnable {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + " 完成任务");
            } catch (InterruptedException e) {
               e.printStackTrace();
            } finally {
                latch.countDown(); //完成任务后计数减1
            }
        }
    }
}

在这个例子中,我们创建了一个固定大小的线程池来执行5个WorkerThread任务。每个工作线程完成自己的任务后会调用latch.countDown()减少计数器的值。主线程则通过调用latch.await()等待,直到所有的工作线程都完成了它们的任务(即计数器变为0),之后主线程才会继续执行。相对于join(),CountDownLatch使用起来非常方便。

稍微修改一下上面的示例,就得到以下控制多个线程同时开始执行例子:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchDemo {
    public static int threadCount = 5;
    public static ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
    public static CountDownLatch latch = new CountDownLatch(1);

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < threadCount; ++i) {
            executorService.execute(new WorkerThread());
        }
        Thread.sleep(3000);
        latch.countDown();
        executorService.shutdown();
    }

    static class WorkerThread implements Runnable {
        @Override
        public void run() {
            try {
                latch.await();
                System.out.println(Thread.currentThread().getName() + " 开始执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

上述示例中将计数器CountDownLatch初始化为1,所有线程都阻塞在await()上,主线程等待3秒后调用countDown()将计数器减为0,于是所有子线程都同时被唤醒,并开始执行,这样就可以模拟多个线程同时并发执行的情况。

参考

CountDownLatch的 常用场景及使用示例_countdownlatch应用场景-CSDN博客


原文地址:https://blog.csdn.net/qq_38875964/article/details/142552771

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!