线程池和CountDownLatch搭配使用

发布于:2024-05-06 ⋅ 阅读:(27) ⋅ 点赞:(0)

一,CountDownLatch

CountDownLatch是Java并发编程中用于线程间协调的一个同步辅助类。它通过一个初始计数值来控制线程的等待,这个计数值在其他线程执行特定任务时递减。

  1. 初始化:创建CountDownLatch实例时,你需要指定一个整数值,该值代表需要等待的事件或任务的数量。

  2. 递减计数countDown()方法用于减少CountDownLatch的当前计数值。每当一个关联的操作执行完毕,就调用此方法,从而向等待的线程发出信号。

  3. 等待完成await()方法用于阻塞当前线程,直到CountDownLatch的计数值达到0。这意味着主线程或其他等待的线程会在执行了await()调用的地方暂停,直到所有相关的countDown()操作完成。

  4. 灵活性countDown()可以被同一个线程多次调用,每次调用都会导致计数值减少。同时,如果有多个线程都在等待,它们会共享同一个CountDownLatch的计数值,当计数值减到0时,所有等待的线程都会被唤醒。

  5. 超时机制await()方法还可以接受一个超时时间参数,这样即使计数值没有在规定时间内减到0,等待的线程也会被唤醒,避免无限期等待。

  6. 结果汇总:在所有任务执行完毕后,主线程可以安全地继续执行,此时可以对子线程中的任务结果进行汇总或后续处理。

通过这种方式,CountDownLatch确保了在所有预定的任务或事件完成之前,主线程或其他线程不会过早地继续执行,从而实现了线程间的协调和同步。

二,示例

public class 多线程结合countdownlatch {

    public static void main(String[] args) {
        //模拟任务
        List<String> records = new ArrayList<>();
        records.add("rc1");
        records.add("rc2");
        //线程池
        System.out.println("开始执行");
        ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        CountDownLatch latch = new CountDownLatch(records.size());
        records.forEach(record->{
            service.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(record);
                        Thread.sleep(2000);//执行业务逻辑
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }finally {
                        latch.countDown();
                    }
                }
            });
        });
        try {
            latch.await(30, TimeUnit.MINUTES);//设置超时时间 防止无限期等待
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("执行完成");
    }
}

三,使用场景

场景一:CountDownLatch 非常适合于对任务进行拆分,使其并行执行,比如某个任务执行2s,其对数据的请求可以分为五个部分,那么就可以将这个任务拆分为5个子任务,分别交由五个线程执行,执行完成之后再由主线程进行汇总,此时,总的执行时间将决定于执行最慢的任务,平均来看,还是大大减少了总的执行时间。
场景二:使用 CountDownLatch 的地方是使用某些外部链接请求数据的时候,比如图片。在本人所从事的项目中就有类似的情况,因为我们使用的图片服务只提供了获取单个图片的功能,而每次获取图片的时间不等,一般都需要1.5s~2s。当我们需要批量获取图片的时候,比如列表页需要展示一系列的图片,如果使用单个线程顺序获取,那么等待时间将会极长,此时我们就可以使用CountDownLatch对获取图片的操作进行拆分,并行的获取图片,这样也就缩短了总的获取时间。