Loading... # CompletableFuture的使用及示例代码 **目录** 1. 引言 2. CompletableFuture概述 3. 基本使用方法 4. 进阶用法解析 5. 实际案例示例 6. 原理解析 7. 总结 --- ## 一、引言 在现代Java开发中,**异步编程**已经成为提高应用性能和响应速度的重要手段。`CompletableFuture`作为Java 8引入的强大工具,为开发者提供了简洁而强大的方式来编写异步、非阻塞的代码。😊 ## 二、CompletableFuture概述 ### 1. 什么是CompletableFuture `CompletableFuture`是Java中的一个类,属于 `java.util.concurrent`包。它实现了 `Future`接口,并提供了**完成(complete)**计算结果的能力,以及**链式**和**组合式**的异步操作。 ### 2. 主要特点 - **支持链式调用**:可以通过一系列方法链,依次执行多个异步任务。 - **异步执行**:支持异步执行任务,避免主线程阻塞。 - **组合功能**:可以组合多个 `CompletableFuture`,实现复杂的异步流程。 ## 三、基本使用方法 ### 1. 创建CompletableFuture对象 #### 1.1 使用 `supplyAsync`方法 ```java CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // 异步任务 return "Hello, World!"; }); ``` **解释**: - `CompletableFuture.supplyAsync()`:静态方法,接受一个 `Supplier`接口,用于异步执行有返回值的任务。 - `() -> {}`:Lambda表达式,表示要执行的任务。 #### 1.2 使用 `runAsync`方法 ```java CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { // 异步任务 System.out.println("执行异步任务"); }); ``` **解释**: - `CompletableFuture.runAsync()`:用于执行没有返回值的异步任务。 ### 2. 获取异步结果 #### 2.1 使用 `get()`方法 ```java String result = future.get(); ``` **解释**: - `future.get()`:阻塞方法,等待异步任务完成,获取结果。 #### 2.2 使用 `join()`方法 ```java String result = future.join(); ``` **解释**: - `future.join()`:类似于 `get()`,但在发生异常时会抛出 `CompletionException`。 ### 3. 回调方法 #### 3.1 `thenApply`方法 ```java CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> { return "42"; }).thenApply(s -> Integer.parseInt(s)); ``` **解释**: - `thenApply()`:当上一个阶段完成后,执行一个函数,处理结果并返回新的值。 #### 3.2 `thenAccept`方法 ```java future.thenAccept(result -> { System.out.println("结果是:" + result); }); ``` **解释**: - `thenAccept()`:处理结果,但不返回新的值。 #### 3.3 `thenRun`方法 ```java future.thenRun(() -> { System.out.println("任务完成!"); }); ``` **解释**: - `thenRun()`:不关心结果,只在任务完成后执行操作。 ## 四、进阶用法解析 ### 1. 组合多个CompletableFuture #### 1.1 `thenCompose`方法 用于将两个异步操作进行**流水线**式的组合。 ```java CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { return "Hello"; }).thenCompose(s -> CompletableFuture.supplyAsync(() -> { return s + ", World!"; })); ``` **解释**: - `thenCompose()`:接收一个返回 `CompletableFuture`的函数,将两个异步操作串联。 #### 1.2 `thenCombine`方法 用于将两个独立的异步操作的结果进行合并。 ```java CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 2); CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 3); CompletableFuture<Integer> result = future1.thenCombine(future2, (a, b) -> a + b); ``` **解释**: - `thenCombine()`:接收另一个 `CompletableFuture`和合并函数,将两个结果进行合并。 ### 2. 异常处理 #### 2.1 `exceptionally`方法 ```java CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { if (true) { throw new RuntimeException("发生异常"); } return "Success"; }).exceptionally(ex -> { System.out.println("异常:" + ex.getMessage()); return "默认值"; }); ``` **解释**: - `exceptionally()`:当任务发生异常时,执行异常处理函数。 #### 2.2 `handle`方法 ```java CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { throw new RuntimeException("错误"); }).handle((result, ex) -> { if (ex != null) { return "处理后的默认值"; } return result; }); ``` **解释**: - `handle()`:无论任务是否异常,都会执行处理函数,可根据异常情况返回不同结果。 ### 3. 自定义线程池 ```java ExecutorService executor = Executors.newFixedThreadPool(3); CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { // 任务代码 }, executor); ``` **解释**: - **自定义线程池**:使用 `ExecutorService`指定任务执行的线程池,避免默认的 `ForkJoinPool`。 ## 五、实际案例示例 ### 案例:模拟商品价格查询 假设我们需要从三个电商平台获取某商品的价格,并取最低价。 #### 1. 实现代码 ```java public class PriceFetcher { public static void main(String[] args) throws Exception { CompletableFuture<Double> priceFromShopA = CompletableFuture.supplyAsync(() -> { delay(); return 100.0; }); CompletableFuture<Double> priceFromShopB = CompletableFuture.supplyAsync(() -> { delay(); return 105.0; }); CompletableFuture<Double> priceFromShopC = CompletableFuture.supplyAsync(() -> { delay(); return 98.0; }); CompletableFuture<Void> allOf = CompletableFuture.allOf(priceFromShopA, priceFromShopB, priceFromShopC); CompletableFuture<Double> minPrice = allOf.thenApply(v -> { try { return Math.min(priceFromShopA.get(), Math.min(priceFromShopB.get(), priceFromShopC.get())); } catch (Exception e) { throw new RuntimeException(e); } }); System.out.println("最低价格:" + minPrice.get()); } private static void delay() { try { Thread.sleep((long)(Math.random() * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } } } ``` **解释**: - **`priceFromShopA/B/C`**:分别从三个“商店”异步获取价格。 - **`CompletableFuture.allOf()`**:等待所有异步操作完成。 - **`minPrice`**:在所有操作完成后,计算最低价格。 - **`delay()`**:模拟网络延迟。 #### 2. 运行结果 ``` 最低价格:98.0 ``` **解释**: - 输出最低的价格 `98.0`,表示从三个异步任务中获取结果并进行处理。 ## 六、原理解析 ### 1. CompletableFuture的工作原理 `CompletableFuture`内部维护了一个状态机,包含以下状态: - **未完成(Pending)** - **已完成(Completed)** - **异常完成(Exceptionally Completed)** 当调用异步方法时,任务被提交到线程池执行,执行完成后更新状态,并触发相关的回调方法。 **图1:CompletableFuture状态转换图** 📊 ```mermaid graph TD A[Pending] --> B[Completed] A --> C[Exceptionally Completed] ``` **解释**: - **Pending**:初始状态,任务尚未完成。 - **Completed**:任务成功完成。 - **Exceptionally Completed**:任务因异常完成。 ### 2. 异步流水线 通过 `thenApply`、`thenCompose`等方法,可以将多个异步操作串联,形成**异步流水线**。 **公式1:异步操作组合** $$ CompletableFuture_{result} = CompletableFuture_{task1}.thenCompose(task2) $$ - **`CompletableFuture_{task1}`**:第一个异步任务。 - **`task2`**:依赖 `task1`结果的第二个异步任务。 ## 七、总结 `CompletableFuture`为Java提供了强大的异步编程能力,支持链式调用、组合异步操作和异常处理等功能。在高并发和异步需求的场景中,合理使用 `CompletableFuture`可以显著提升应用性能和用户体验。👍 --- **重点提示**: - **`CompletableFuture`支持异步非阻塞编程**。🔑 - **`thenApply`、`thenCompose`等方法用于组合异步操作**。🔑 - **使用 `exceptionally`和 `handle`方法处理异步任务中的异常**。🔑 --- **思维导图:CompletableFuture的主要功能** ```mermaid graph TD A[CompletableFuture] -->B[创建异步任务] -->B1[supplyAsync] -->B2[runAsync] -->C[组合异步操作] -->C1[thenApply] -->C2[thenCompose] -->C3[thenCombine] -->D[异常处理] -->D1[exceptionally] -->D2[handle] -->E[自定义线程池] ``` --- **表1:CompletableFuture常用方法对比** 📋 | 方法名 | 功能描述 | 是否有返回值 | | ----------------- | ---------------------------- | ------------ | | `supplyAsync` | 异步执行任务并返回结果 | 是 | | `runAsync` | 异步执行任务,无返回结果 | 否 | | `thenApply` | 处理结果并返回新的结果 | 是 | | `thenAccept` | 处理结果,无返回新值 | 否 | | `thenCompose` | 将多个异步任务串联 | 是 | | `thenCombine` | 合并两个异步任务的结果 | 是 | | `exceptionally` | 处理异常并返回默认值 | 是 | | `handle` | 处理结果或异常,返回新的结果 | 是 | --- 希望通过本文的介绍,您能够深入理解**CompletableFuture**的使用方法,并在实际开发中灵活运用,提升代码的异步处理能力。🚀 最后修改:2024 年 10 月 07 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏