当异步任务汇聚,你该如何选择:CountDownLatch 与 CompletableFuture 对比

当我们需要执行多个异步任务,并且需要等待它们全部完成才可以继续时,可以使用以下两种实现方案:

一、方案

方案一:CountDownLatch

CountDownLatch是一个同步工具类,可以用来实现多个线程之间的同步。它可以让一个线程等待其他线程完成某些工作后再继续执行。

实现方案如下:

arduino 复制代码
import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {

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

        // 启动三个线程执行任务
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                // 执行任务
                System.out.println(Thread.currentThread().getName() + " 执行任务");
                latch.countDown();
            }).start();
        }

        // 阻塞着,等待所有任务完成
        latch.await();

        // 所有任务完成后,继续执行
        System.out.println("所有任务完成");
    }
}

输出结果:

复制代码
Thread-1 执行任务
Thread-0 执行任务
Thread-2 执行任务
所有任务完成

方案二:CompletableFuture

CompletableFuture是一个异步编程的工具类,可以用来执行异步任务并获取任务执行结果。

实现方案如下:

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CompletableFutureDemo {

    public static void main(String[] args) throws InterruptedException, 
    ExecutionException {
        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        // 启动三个异步任务
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            // 执行任务1
            System.out.println("任务1 执行");
        }, executorService);
        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
            // 执行任务2
            System.out.println("任务2 执行");
        }, executorService);
        CompletableFuture<Void> future3 = CompletableFuture.runAsync(() -> {
            // 执行任务3
            System.out.println("任务3 执行");
        }, executorService);

        // 等待所有任务完成
        CompletableFuture.allOf(future1, future2, future3).get();

        // 所有任务完成后,继续执行
        System.out.println("所有任务完成");
    }
}

如果任务比较多的情况下就可以使用数组列表来存储创建的任务,CompletableFuture.allOf接收的是CompletableFuture<?>[]数组。

输出结果:

复制代码
任务1 执行
任务2 执行
任务3 执行
所有任务完成
  • CountDownLatch 方案中,我们使用 latch.await() 方法来等待所有任务完成。
  • CompletableFuture 方案中,我们使用 CompletableFuture.allOf() 方法来等待所有任务完成。

两种方案各有优缺点:

  • CountDownLatch 方案简单易用,但需要额外创建一个 CountDownLatch 对象。
  • CompletableFuture 方案可以获取任务的执行结果,但需要额外创建一个 CompletableFuture 对象。

在实际使用中,可以根据具体需求选择合适的方案。

二、CountDownLatch vs CompletableFuture

CountDownLatch 和 CompletableFuture 都是用于在多线程环境中同步线程的工具。它们都具有各自的优缺点,适用于不同的场景。

特性 CountDownLatch CompletableFuture
功能 简单的同步 丰富的同步、异步、通信功能
使用难度 简单 复杂
适用场景 简单的同步场景 各种同步、异步场景

CountDownLatch

CountDownLatch 是一个计数器,它可以让一个线程等待其他线程完成某些操作。CountDownLatch 的计数器初始值为某个整数,当计数器的值减为 0 时,所有等待的线程都会被唤醒。

CountDownLatch 的优点是简单易用,适用于一些简单的同步场景。例如,可以使用 CountDownLatch 来实现线程池的启动和关闭。

CountDownLatch 的缺点是它只能实现简单的同步场景。例如,如果需要在多个线程之间传递数据,CountDownLatch 就无法实现。

CompletableFuture

CompletableFuture 是一个异步任务处理框架,它可以用于在多线程环境中异步执行任务、同步多个异步任务的结果、以及实现线程间通信等。

CompletableFuture 的优点是功能丰富,适用于各种同步场景。例如,可以使用 CompletableFuture 来实现线程池的异步执行、多个异步任务的结果同步、以及线程间数据传递等。

CompletableFuture 的缺点是使用起来比较复杂,需要一定的学习成本。

三、相关题目

  1. CountDownLatch 的使用场景有哪些?

答案:CountDownLatch 可以用于以下场景:

  • 等待其他线程完成任务后再执行某些操作。例如,可以使用 CountDownLatch 来实现线程池的启动和关闭。
  • 让多个线程同步执行某些操作。例如,可以使用 CountDownLatch 来实现多个线程并发读取文件。
  1. CompletableFuture 是什么?

答案:CompletableFuture 是一个异步任务处理框架,它可以用于在多线程环境中异步执行任务、同步多个异步任务的结果、以及实现线程间通信等。

  1. CompletableFuture 的使用场景有哪些?

答案:CompletableFuture 可以用于以下场景:

  • 异步执行任务。例如,可以使用 CompletableFuture 来实现异步 HTTP 请求。
  • 同步多个异步任务的结果。例如,可以使用 CompletableFuture 来实现多个线程并发计算的结果求和。
  • 实现线程间通信。例如,可以使用 CompletableFuture 来实现线程间的数据传递。
  1. CompletableFuture 的常用方法有哪些?

答案:CompletableFuture 提供了丰富的 API,常用的方法包括:

  • thenApply():将当前 CompletableFuture 的结果作为参数传递给一个函数,并将函数的结果作为新的 CompletableFuture。
  • thenAccept():将当前 CompletableFuture 的结果作为参数传递给一个函数,但不返回任何结果。
  • thenRun():不依赖当前 CompletableFuture 的结果,执行一个函数。
  • allOf():将多个 CompletableFuture 组合成一个新的 CompletableFuture,只有当所有 CompletableFuture 都完成时,新的 CompletableFuture 才会完成。
  • anyOf():将多个 CompletableFuture 组合成一个新的 CompletableFuture,当任意一个 CompletableFuture 完成时,新的 CompletableFuture 就会完成。
  1. CompletableFuture 的异常处理机制是怎样的?

答案:CompletableFuture 的异常处理机制如下:

  • 如果 CompletableFuture 的执行过程中抛出异常,则异常会被封装在一个 CompletionException 中,并传递给 thenApply()、thenAccept() 等方法。
  • 如果 CompletableFuture 的执行过程中没有抛出异常,则 thenApply()、thenAccept() 等方法不会抛出异常。
  1. CompletableFuture 和 CountDownLatch 的区别是什么?

答案:CompletableFuture 和 CountDownLatch 都是用于在多线程环境中同步线程的工具,但它们有以下区别:

  • 功能:CompletableFuture 具有更丰富的功能,可以用于异步执行任务、同步多个异步任务的结果、以及实现线程间通信等,而 CountDownLatch 只能用于简单的同步场景。
  • 使用难度:CompletableFuture 的使用难度比 CountDownLatch 高,需要一定的学习成本。
  • 适用场景:CompletableFuture 适用于各种同步场景,而 CountDownLatch 适用于简单的同步场景。
相关推荐
江城开朗的豌豆6 分钟前
JavaScript篇:自定义事件:让你的代码学会'打小报告'
前端·javascript·面试
风铃儿~10 分钟前
Spring AI 入门:Java 开发者的生成式 AI 实践之路
java·人工智能·spring
斯普信专业组15 分钟前
Tomcat全方位监控实施方案指南
java·tomcat
忆雾屿26 分钟前
云原生时代 Kafka 深度实践:06原理剖析与源码解读
java·后端·云原生·kafka
武昌库里写JAVA39 分钟前
iview Switch Tabs TabPane 使用提示Maximum call stack size exceeded堆栈溢出
java·开发语言·spring boot·学习·课程设计
gaoliheng0061 小时前
Redis看门狗机制
java·数据库·redis
我是唐青枫1 小时前
.NET AOT 详解
java·服务器·.net
Su米苏1 小时前
Axios请求超时重发机制
java
Undoom2 小时前
🔥支付宝百宝箱新体验!途韵归旅小帮手,让高铁归途变旅行
后端
工呈士2 小时前
MobX与响应式编程实践
前端·react.js·面试