CompletableFuture的使用
创始人
2025-05-31 10:10:56
0

目录

一、前言

二、概念介绍 

三、自身特性

四、使用方式

1、异步执行一个任务并获取结果

2、异步执行一个任务并处理异常

3、异步执行多个任务并合并结果

4、异步执行多个任务并处理其中一个任务的结果

5、串行执行多个任务

6、 检查异步任务是否执行完成和执行回调

五、使用场景


一、前言

现在大部分的CPU都是多核,我们都知道想要提升我们应用程序的运行效率,就必须得充分利用多核CPU的计算能力;Java为我们提供了大量多线程API,使用它们可以让我们的代码避免同步阻塞,进而达到提升运行效率的目的,CompletableFuture就是其中一个非常强大且重要API,下面我们就来介绍一下CompletableFuture的概念和使用。

二、概念介绍 

CompletableFuture 是 Java 8 中新增的一个异步编程工具类,它是基于 Future 和 CompletionStage 接口构建的,可以与 Java 8 中的 Stream API 配合使用,也能够与 Java 9 中的 Reactive Stream API 进行交互。

主要用于异步执行任务并返回结果,实现异步计算和操作组合。它提供了一种灵活、可组合的方式来实现异步计算,同时也提供了异常处理、取消、超时等特性。在CompletableFuture中,我们可以通过回调函数来处理任务的结果,也可以使用其它方法来组合多个CompletableFuture对象,以构建更复杂的异步操作流水线。

三、自身特性

  1. 异步执行:CompletableFuture 可以在新的线程上异步执行计算或操作,从而不会阻塞主线程,提高程序的响应速度。

  2. 可组合性:CompletableFuture 的操作可以组合成一个或多个的 CompletableFuture 对象,从而构成复杂的异步计算链。

  3. 异常处理:CompletableFuture 可以对异常进行处理,通过 exceptionally() 方法可以捕获计算中的异常并返回默认值。

  4. 取消与超时:CompletableFuture 支持取消异步任务,还可以设置超时时间来避免任务的无限等待。

  5. 非阻塞式等待:CompletableFuture 提供了非阻塞式的等待方法,如 join() 和 getNow() 方法。

四、使用方式

1、异步执行一个任务并获取结果

通过 CompletableFuture 的静态方法 supplyAsync() 可以异步执行一个任务,返回 CompletableFuture 对象,通过该对象可以获取任务执行的结果。

CompletableFuture future = CompletableFuture.supplyAsync(() -> {// 执行一些耗时的操作return "Hello CompletableFuture";
});
String result = future.get(); // 阻塞等待任务执行完成并获取结果
System.out.println(result);

2、异步执行一个任务并处理异常

CompletableFuture 提供了方法 handle() 来处理异步任务执行过程中的异常,它可以处理任务完成时的异常,也可以处理任务执行过程中的异常。

CompletableFuture future = CompletableFuture.supplyAsync(() -> {// 执行一些可能会出现异常的操作throw new RuntimeException("Something went wrong");
}).handle((result, exception) -> {if (exception != null) {System.out.println("Task failed with exception: " + exception);return "default value";} else {return result;}
});
String result = future.get();
System.out.println(result);

3、异步执行多个任务并合并结果

通过 CompletableFuture 的静态方法 allOf() 可以并行执行多个任务,等待所有任务完成后,通过 CompletableFuture.join() 方法合并所有任务的结果。

CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture future2 = CompletableFuture.supplyAsync(() -> "CompletableFuture");
CompletableFuture future3 = CompletableFuture.supplyAsync(() -> "Java");CompletableFuture combinedFuture = CompletableFuture.allOf(future1, future2, future3);
combinedFuture.get();String result = Stream.of(future1, future2, future3).map(CompletableFuture::join).collect(Collectors.joining(" "));
System.out.println(result);

CompletableFuture 提供了三种方法来处理它们:handle()、whenComplete() 和 exceptionly()。这里就不做详细介绍了,有兴趣的朋友们可以自己去详细了解一下,以下为各种处理方式的比较结果。 

handle()whenComplete()exceptionly()
访问成功YesYesNo
访问失败YesYesYes
能从失败中恢复YesNoYes
能转换结果从T 到 UYesNoNo
成功时触发YesYesNo
失败时触发YesYesYes
有异步版本YesYesYes(12版本)

4、异步执行多个任务并处理其中一个任务的结果

通过 CompletableFuture 的静态方法 anyOf() 可以并行执行多个任务,只要有一个任务完成,就会立即返回其结果。

CompletableFuture future1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}return "Result 1";
});
CompletableFuture future2 = CompletableFuture.supplyAsync(() -> "Result 2");
CompletableFuture future3 = CompletableFuture.supplyAsync(() -> "Result 3");CompletableFuture anyOfFuture = CompletableFuture.anyOf(future1, future2, future3);Object result = anyOfFuture.get();
System.out.println(result);
 

5、串行执行多个任务

通过 CompletableFuture 的方法 thenApply()、thenAccept() 和 thenRun() 可以串行执行多个任务,每个任务在前一个任务完成后才会执行。

CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture future2 = future1.thenApply(result -> result + " CompletableFuture");
CompletableFuture future3 = future2.thenAccept(result -> System

6、 检查异步任务是否执行完成和执行回调

CompletableFuture中,可以使用isDone()方法来检查异步任务是否已经执行完毕。该方法会返回一个boolean类型的值,表示异步任务是否已经完成。如果异步任务已经完成,则可以通过调用get()方法获取其返回值;如果异步任务还没有完成,则可以通过注册回调函数来等待其完成。

CompletableFuture future = CompletableFuture.supplyAsync(() -> {// 异步任务return "Hello, World!";
});// 检查异步任务是否已经完成
if (future.isDone()) {// 获取异步任务的返回值String result = future.get();System.out.println(result);
} else {// 注册回调函数,在异步任务完成时获取其返回值future.thenAccept(result -> {System.out.println(result);});
}

五、使用场景

在调用第三方同步API时,我们通常需要等待API返回结果后才能继续执行后续代码,这可能会导致系统的吞吐量较低,影响用户的体验。使用CompletableFuture可以在异步执行API请求的同时,继续执行后续代码,从而提高系统的吞吐量。
下面是一个使用CompletableFuture提高系统吞吐量的示例代码。

public class APIService {public String getDataFromAPI(String url) {// 同步请求APIString result = request(url);return result;}public CompletableFuture getDataFromAPIAsync(String url) {// 异步请求APICompletableFuture future = CompletableFuture.supplyAsync(() -> request(url));return future;}private String request(String url) {// 请求API并返回结果try {// 打印线程和请求参数,观察结果帮助理解System.out.println(Thread.currentThread().getName());System.out.println(url);// 睡眠模拟请求耗时TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {throw new RuntimeException(e);}return "success";}
}

在上面的代码中,getDataFromAPI方法是同步请求API的方法,会阻塞后续代码的执行。而getDataFromAPIAsync方法则是使用CompletableFuture异步请求API的方法,不会阻塞后续代码的执行,而是返回一个CompletableFuture对象,代表API请求的异步任务。

我们可以在后续代码中继续执行其他任务,等到异步任务完成后再获取结果。

public class Main {public static void main(String[] args) {APIService service = new APIService();CompletableFuture future1 = service.getDataFromAPIAsync("https://api.example.com/data1");CompletableFuture future2 = service.getDataFromAPIAsync("https://api.example.com/data2");// 继续执行其他任务System.out.println("执行其他任务...");// 等待异步任务完成并获取结果String result1 = future1.join();String result2 = future2.join();// 处理结果System.out.println("处理结果...");}
}

在上面的代码中,我们使用了CompletableFuture异步请求两个API,并在后续代码中继续执行其他任务。当异步任务完成后,我们使用join方法获取结果,并处理结果。

除了使用join方法获取结果外,使用get方法也可以获取结果。我们还可以使用thenApplythenAcceptthenCompose等方法对异步任务的结果进行处理。另外,当我们需要等待多个异步任务的完成并获取结果时,可以使用前面介绍的allOfanyOf方法。

相关内容

热门资讯

Android开发-Andro... 01  Android UI 1.1  UI 用户界面(User Interface,...
有关于致父母的一封感谢信 给父... 父母的教育素质影响着学前儿童家庭教育的效果和质量,也直接决定着家庭教育的优劣成败。那么有关于致父母的...
有关于写给老师的一封感谢信 给... 感谢信作为一种礼貌性言语行为的载体,其中谢意表达的处理成为写好感谢信的核心环节。下面小编整理了有关于...
有关于致干部家属的感谢信 致干... 感谢信是写信人对给予自己帮助、支持、关心、祝贺、慰问、馈赠的施惠人表示答谢而写的社交礼仪书信。下面小...
婚礼主持词开场白,浪漫婚礼主持... 1、开场白:(神秘花园)  我们每个人都生长在同一个蔚蓝的星球;我们每个人都是从平坦或不平坦的一端开...
有关于致公交司机的感谢信 给公... 公交司机作为影响城市公共交通供给质量和服务满意度的双重介入主体,其个体行为在很大程度上代表了城市综合...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
有关于写给公安机关的感谢信 写... 公安机关内部管理制度是否完善,对于确保公安队伍建设和管理,保证公安机关顺利地履行职责和任务,具有重大...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
有关于写给公安局的一封感谢信 ... 公安局对固定资产指标的要求也越来越多,固定资产管理工作成为公安局日常一项很重要的工作。那么xxx应该...
有关于致公交公司的感谢信 给公... 公交公司的生产经营活动不仅具有经济效益,而且具有社会效益。那么xxx应该怎么写呢?下面小编整理了有关...
有关于优秀员工致公司的感谢信 ... 有对自然物象的感谢,对伟大人物的感谢,更有对日常生活的感谢。那么关于优秀员工致公司的感谢信应该怎么写...
有关于员工致公司领导的感谢信 ... 谢语是以表达感谢为要点。那么有关于员工致公司领导的感谢信应该怎么写呢?下面小编整理了有关于员工致公司...
药品批准文号查询|药融云-中国... 药品批文是国家食品药品监督管理局(NMPA)对药品的审评和批准的证明文件...
最新或2023(历届)给公司领...  给公司领导的感谢信范文一:  敬爱的领导:  你们好,回想在港城办事处三年多的日子里,我得到了各位...
最新或2023(历届)企业致客...   企业致客户的感谢信范文一:  尊敬的客户:  您好!  新的一年就要到来了,怀着感恩的心情,向您...
给公司捐款的感谢信范文 公司捐...  给公司捐款的感谢信范文一:  尊敬的领导、工友们:  你们好!首先我想表达我们一家人最诚挚的谢意和...
python 基础系列篇:四、... python 基础系列篇:四、编写两个简单的小游戏(猜数字及2048&#...
写给居委会的感谢信范文 怎么给... 写给居委会的感谢信范文一:  尊敬的上汽社区居委会领导们:  您们好!  首先感谢上汽社区居委会的各...
最新或2023(历届)终给客户...  年终给客户的感谢信范文一:  尊敬的客户:  您好!新的一年即将到来,我们怀着感恩的心情向您致以亲...