CompletableFuture详细讲解

news/2024/10/21 7:45:16/

目录

一、基本概念

1.1 异步编程

CompletableFuture%E7%AE%80%E4%BB%8B-toc" style="margin-left:120px;">1.2 CompletableFuture简介

CompletableFuture-toc" style="margin-left:80px;">二、创建和完成CompletableFuture

CompletableFuture%E5%AF%B9%E8%B1%A1-toc" style="margin-left:120px;">2.1 创建CompletableFuture对象

CompletableFuture-toc" style="margin-left:120px;">2.2 手动完成CompletableFuture

CompletableFuture-toc" style="margin-left:120px;">2.3 异常完成CompletableFuture

三、异步计算和回调

3.1 异步任务的执行

3.2 处理计算结果

CompletableFuture-toc" style="margin-left:80px;">四、组合多个CompletableFuture

4.1 thenCombine

4.2 thenCompose

4.3 allOf和anyOf

五、异常处理

5.1 handle

5.2 exceptionally

六、高级特性

6.1 自定义执行器

6.2 超时控制

七、实战案例

7.1 需求描述

7.2 代码实现


Java的CompletableFuture是Java 8中引入的一个功能强大的类,用于处理异步编程。它不仅提供了一种方式来表示异步计算,还提供了丰富的API来进行复杂的异步编排和处理。本文将详细讲解CompletableFuture的基本概念、使用方法以及一些高级特性,并结合实例代码进行说明。

一、基本概念

1.1 异步编程

异步编程是一种并发编程的形式,通过非阻塞方式执行任务。传统的同步编程中,任务必须按顺序执行,每个任务必须等待前一个任务完成。然而,在异步编程中,任务可以在后台执行,主线程无需等待任务完成,因而可以继续处理其他任务。这种方式在提高程序响应速度和资源利用率方面有很大优势。

CompletableFuture%E7%AE%80%E4%BB%8B">1.2 CompletableFuture简介

CompletableFuture是Java提供的一个实现Future接口的类,它不仅支持传统的Future接口方法,还引入了许多新的方法来支持回调、组合、处理异常等功能。通过这些方法,开发者可以更方便地编写异步代码。

CompletableFuture">二、创建和完成CompletableFuture

CompletableFuture%E5%AF%B9%E8%B1%A1">2.1 创建CompletableFuture对象

创建一个CompletableFuture对象非常简单,可以通过以下几种方式:

  1. 使用CompletableFuture的静态工厂方法:

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello, World!");
  2. 使用默认构造函数创建一个空的CompletableFuture,然后在未来的某个时间点手动完成它:

    CompletableFuture<String> future = new CompletableFuture<>();
    // 在其他线程或任务中完成这个future
    future.complete("Hello, World!");
CompletableFuture">2.2 手动完成CompletableFuture

你可以通过complete方法手动完成一个CompletableFuture

CompletableFuture<String> future = new CompletableFuture<>();
future.complete("Hello, World!");

如果已经完成的CompletableFuture再次调用complete,将不会改变其状态。

CompletableFuture">2.3 异常完成CompletableFuture

CompletableFuture也可以以异常方式完成:

CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new RuntimeException("Something went wrong"));

三、异步计算和回调

3.1 异步任务的执行

CompletableFuture提供了多种方法来启动异步任务,例如:

  • runAsync:执行不返回结果的异步任务。

  • supplyAsync:执行并返回结果的异步任务。

java">CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {// 异步执行的任务System.out.println("Hello from a different thread!");
});
​
CompletableFuture<String> futureWithResult = CompletableFuture.supplyAsync(() -> {// 异步执行的任务,返回结果return "Result of the async computation";
});
3.2 处理计算结果

CompletableFuture提供了多种方法来处理异步任务的结果,例如:

java">CompletableFuture.supplyAsync(() -> "Hello").thenApply(result -> result + ", World!").thenAccept(System.out::println);

上述代码中,supplyAsync方法执行异步任务并返回结果"Hello"。thenApply方法对结果进行处理,得到"Hello, World!"。thenAccept方法消费处理后的结果,并打印输出。

CompletableFuture">四、组合多个CompletableFuture

CompletableFuture提供了多种方式来组合多个异步任务:

4.1 thenCombine

thenCombine用于将两个CompletableFuture的结果进行组合,并返回一个新的CompletableFuture

java">CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");
​
CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + " " + result2);
combinedFuture.thenAccept(System.out::println); // 输出 "Hello World"
4.2 thenCompose

thenCompose用于将一个CompletableFuture的结果作为另一个CompletableFuture的输入,类似于flatMap

java">CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello").thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " World"));
​
future.thenAccept(System.out::println); // 输出 "Hello World"
4.3 allOfanyOf
java">CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Result from future1");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Result from future2");
​
CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2);
allOfFuture.thenRun(() -> System.out.println("All futures completed"));
​
CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(future1, future2);
anyOfFuture.thenAccept(result -> System.out.println("First completed future result: " + result));

五、异常处理

在处理异步任务时,异常处理是不可避免的。CompletableFuture提供了多种方式来处理异常:

5.1 handle

handle方法用于处理正常结果和异常情况:

java">CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {if (Math.random() > 0.5) {throw new RuntimeException("Something went wrong");}return "Success";
});
​
future.handle((result, ex) -> {if (ex != null) {return "Exception: " + ex.getMessage();}return result;
}).thenAccept(System.out::println);
5.2 exceptionally

exceptionally方法仅处理异常情况:

java">CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {if (Math.random() > 0.5) {throw new RuntimeException("Something went wrong");}return "Success";
});
​
future.exceptionally(ex -> "Exception: " + ex.getMessage()).thenAccept(System.out::println);

六、高级特性

6.1 自定义执行器

默认情况下,CompletableFuture使用ForkJoinPool.commonPool()作为其默认的线程池。你可以自定义执行器来控制任务的执行方式:

java">Executor executor = Executors.newFixedThreadPool(10);
​
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello", executor).thenApplyAsync(result -> result + " World", executor);
​
future.thenAcceptAsync(System.out::println, executor);
6.2 超时控制

在某些场景下,处理超时是必要的。Java 9引入了orTimeoutcompleteOnTimeout方法:

java">CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(3000);} catch (InterruptedException e) {throw new IllegalStateException(e);}return "Result";
});
​
future.orTimeout(1, TimeUnit.SECONDS).exceptionally(ex -> "Timeout occurred: " + ex.getMessage()).thenAccept(System.out::println);

七、实战案例

为了更好地理解CompletableFuture,我们来看一个实际的例子:模拟一个复杂的业务场景,包含多个异步任务的组合和处理。

7.1 需求描述

假设我们在开发一个在线购物平台,用户下单时需要进行以下操作:

  1. 验证用户信息。

  2. 检查库存。

  3. 处理支付。

  4. 生成订单。

我们希望这些操作尽可能并行执行,以提高系统的响应速度。

7.2 代码实现
java">import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
​
public class OnlineShopping {
​private static final ExecutorService executor = Executors.newFixedThreadPool(10);
​public static void main(String[] args) {CompletableFuture<Void> orderFuture = CompletableFuture.supplyAsync(() -> verifyUser("user123"), executor).thenCombineAsync(CompletableFuture.supplyAsync(() -> checkInventory("item456"), executor), (userVerified, inventoryChecked) -> {if (userVerified && inventoryChecked) {return processPayment("user123", "
​
item456");} else {throw new RuntimeException("User verification or inventory check failed");}}, executor).thenApplyAsync(paymentProcessed -> generateOrder("user123", "item456"), executor).thenAcceptAsync(order -> System.out.println("Order completed: " + order), executor).exceptionally(ex -> {System.err.println("Order processing failed: " + ex.getMessage());return null;});
​orderFuture.join(); // 等待所有操作完成}
​private static boolean verifyUser(String userId) {// 模拟用户验证System.out.println("Verifying user: " + userId);return true;}
​private static boolean checkInventory(String itemId) {// 模拟库存检查System.out.println("Checking inventory for item: " + itemId);return true;}
​private static boolean processPayment(String userId, String itemId) {// 模拟支付处理System.out.println("Processing payment for user: " + userId + " and item: " + itemId);return true;}
​private static String generateOrder(String userId, String itemId) {// 模拟订单生成System.out.println("Generating order for user: " + userId + " and item: " + itemId);return "Order123";}
}

在这个示例中,我们使用了多个CompletableFuture来并行执行用户验证、库存检查和支付处理。所有任务都在自定义的线程池中执行,最后通过生成订单来完成整个流程。如果在任何一个步骤中发生异常,系统会捕获并处理。


http://www.ppmy.cn/news/1464899.html

相关文章

代码随想录-Day22

235. 二叉搜索树的最近公共祖先 方法一&#xff1a;两次遍历 class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {List<TreeNode> path_p getPath(root, p);List<TreeNode> path_q getPath(root, q);TreeNode anc…

kafka单机安装及性能测试

kafka单机安装及性能测试 Apache Kafka是一个分布式流处理平台&#xff0c;最初由LinkedIn开发&#xff0c;并于2011年开源&#xff0c;随后成为Apache项目。Kafka的核心概念包括发布-订阅消息系统、持久化日志和流处理平台。它主要用于构建实时数据管道和流处理应用&#xff…

通过el-tree自定义渲染网页版工作目录,实现鼠标悬浮显示完整名称、用icon区分文件和文件夹等需求

目录 一、通过el-tree自定义渲染网页版工作目录 1.1、需求介绍 1.2、使用el-tree生成文档目录 1.2.1、官方基础用法 ①效果 ②代码&#xff1a; 1.2.2、自定义文档目录&#xff08;实现鼠标悬浮显示完整名称、用icon区分文件和文件夹&#xff09; ①效果&#xff08;直接效…

golang判断字符串是否base64编码的字符串 可准确判断是或否

非常简单的判断一个字符串是否base64编码的方法&#xff0c;就是使用正则base64自身的解码转码来判断&#xff0c;如果失败则一定不是base64编码&#xff0c;否则是base64编码&#xff1a; // 使用正则自身的解码转码来判断字符串是否是base64&#xff0c;可以判断一定不是。 f…

lua函数执行和虚拟机指令

Stack based vs Register based VM 可直接参考 Stack based vs Register based VM lua函数调用 先看一下lua函数的结构&#xff1a; /* ** Function Prototypes */ typedef struct Proto {CommonHeader;TValue *k; /* constants used by the function */Instruction *code;…

Linux基础指令用户管理002

继Linux基础指令用户管理001我们讲述了创建用户和删除用户&#xff0c;我们讲一下如何设置用户密码以及修改用户信息。 操作系统 CentOS Stream 9 设置用户密码 我们使用passwd指令passwd name [rootlocalhost ~]# passwd wg 更改用户 wg 的密码 。 新的密码&#xff1a; …

反编译 Trino Dockerfile

文章目录 反编译 Trino Dockerfile反编译Dockerfile命令反编译后Dockerfile内容获取 Trino 启动脚本卸载 反编译 Trino Dockerfile 反编译Dockerfile命令 alias dfimage"docker run -v /var/run/docker.sock:/var/run/docker.sock --rm ghcr.io/laniksj/dfimage" d…

AWS安全性身份和合规性之Amazon Macie

Amazon Macie是一项数据安全和数据隐私服务&#xff0c;它利用机器学习&#xff08;ML&#xff09;和模式匹配来发现和保护敏感数据。可帮助客户发现、分类和保护其敏感数据&#xff0c;以及监控其数据存储库的安全性。 应用场景&#xff1a; 敏感数据发现 一家金融服务公司…