【Java异步编程进阶】:精通CompletableFuture组合式操作,简化复杂流程
发布时间: 2024-10-21 08:48:27 阅读量: 30 订阅数: 21
CompletableFuture:Java异步编程利器.pptx.pptx
![【Java异步编程进阶】:精通CompletableFuture组合式操作,简化复杂流程](https://thedeveloperstory.com/wp-content/uploads/2022/09/ThenComposeExample-1024x532.png)
# 1. Java异步编程概述
在现代软件开发中,性能和效率是至关重要的。Java作为一种广泛使用的编程语言,随着多核处理器的普及和高性能计算需求的增加,异步编程逐渐成为提升应用程序性能的关键技术之一。异步编程允许程序在执行长时间操作时不会阻塞主线程,从而提升用户体验和系统吞吐量。
Java平台提供了多种机制来实现异步编程,从传统的`java.util.concurrent`包中的线程池和执行器,到Java 8引入的`CompletableFuture`,开发者可以根据不同的业务场景和性能需求选择合适的异步处理方式。
本章将概述Java异步编程的基本概念和重要性,为后续章节深入探讨`CompletableFuture`的高级用法打下基础。我们将讨论异步编程在Java中的演进,以及它如何帮助开发者构建更高效、响应更快的应用程序。通过阅读本章,读者应能够理解异步编程的基本原则以及它在现代软件开发中的重要性。
# 2. 深入CompletableFuture基础
## 2.1 异步任务的创建和执行
### 2.1.1 使用runAsync和supplyAsync启动异步任务
Java 5 引入了 `java.util.concurrent` 包,它提供了并发工具,包括用于异步编程的 `ExecutorService`。然而,`ExecutorService` 需要手动管理线程池和任务的结果,这在一些情况下显得较为繁琐。从 Java 8 开始,`CompletableFuture` 类提供了一种更简洁的方式来处理异步编程。
`CompletableFuture` 类通过 `runAsync` 和 `supplyAsync` 两个静态方法来创建异步任务。这两个方法都会提交一个 `Runnable` 或 `Callable` 任务到一个默认的线程池(`***monPool()`)。
- `runAsync` 方法用于返回 `void` 的任务,适用于不返回结果的异步操作。
- `supplyAsync` 方法用于返回值的任务,适用于需要返回结果的异步操作。
下面是使用 `runAsync` 和 `supplyAsync` 的一个示例:
```***
***pletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 使用runAsync启动一个没有返回值的异步任务
CompletableFuture<Void> runFuture = CompletableFuture.runAsync(() -> {
System.out.println("Running asynchronously");
});
// 使用supplyAsync启动一个有返回值的异步任务
CompletableFuture<String> supplyFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("Supplying asynchronously");
return "Result from CompletableFuture";
});
// 等待异步任务完成
runFuture.get();
String result = supplyFuture.get();
System.out.println(result);
}
}
```
### 2.1.2 异步任务的状态和生命周期
`CompletableFuture` 提供了多个方法来观察任务的当前状态和生命周期事件。任务可以处于以下几种状态:
- **Not completed**: 任务尚未开始执行。
- **Completed normally**: 任务正常完成,没有异常发生。
- **Completed exceptionally**: 任务因异常而完成。
- **Cancelled**: 任务被显式地取消。
- **Completed with value**: 对于返回值的任务,表示任务正常完成且有返回值。
- **Completed with exception**: 对于返回值的任务,表示任务因异常而完成,但异常被封装成了一个 `CompletionException`。
我们可以使用 `isDone()`, `isCompletedExceptionally()`, `isCancelled()`, 和 `get()` 等方法来检查任务的当前状态。
## 2.2 处理异步任务的结果
### 2.2.1 thenApply、thenAccept和thenRun的区别与应用
`CompletableFuture` 通过一系列的组合方法来处理异步任务的结果。这些方法在完成当前 `CompletableFuture` 后,会根据不同的需求来启动一个新的 `CompletableFuture`。其中三个常用的方法是 `thenApply`, `thenAccept`, 和 `thenRun`:
- `thenApply`: 用于处理结果,并返回一个新的结果。它接收一个函数 `Function<T, U>`,这个函数将应用于 `CompletableFuture` 的结果,返回一个新的 `CompletableFuture<U>`。
```java
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<Integer> thenApplyFuture = future.thenApply(s -> s.length());
```
- `thenAccept`: 用于处理结果,但不返回任何内容。它接收一个消费者 `Consumer<T>`,对结果进行消费,返回一个新的 `CompletableFuture<Void>`。
```java
CompletableFuture<Void> thenAcceptFuture = future.thenAccept(System.out::println);
```
- `thenRun`: 类似于 `thenAccept`,但它不接收结果,而是接收一个 `Runnable`,无返回值,返回一个新的 `CompletableFuture<Void>`。
```java
CompletableFuture<Void> thenRunFuture = future.thenRun(() -> System.out.println("Done with the result"));
```
### 2.2.2 异常处理与thenCompose的结合使用
`thenCompose` 方法用于连接两个异步任务,当第一个任务的结果需要作为第二个任务的输入时,`thenCompose` 将派上用场。它可以接收一个函数 `Function<T, CompletableFuture<U>>`,这个函数将当前 `CompletableFuture` 的结果作为参数返回一个新的 `CompletableFuture<U>`。
```java
CompletableFuture<String> first = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> composedFuture = first.thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World"));
```
`thenCompose` 在处理 `CompletableFuture` 时非常有用,特别是当需要将异步操作的结果进行链式传递时。
## 2.3 链式调用与结果依赖
### 2.3.1 thenApply系列方法的链式组合
`thenApply` 系列方法允许我们链式地处理 `CompletableFuture` 的结果。这些方法包括 `thenApply`, `thenApplyAsync`, `thenAccept`, `thenAcceptAsync`, `thenRun`, 和 `thenRunAsync`。在这些方法中,`Async` 版本会使用默认的线程池或自定义线程池来异步执行其后续步骤,而未带 `Async` 的版本则会尝试同步执行。
以下是一个链式调用的例子:
```java
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(s -> s + " World")
.thenApply(String::toUpperCase)
.thenAccept(System.out::println);
```
### 2.3.2 thenCombine与thenAcceptBoth的合并操作
当需要对两个独立的 `CompletableFuture` 的结果进行合并处理时,可以使用 `thenCombine` 和 `thenAcceptBoth` 方法:
- `thenCombine`: 当两个 `CompletableFuture` 都完成时,会将它们的结果作为参数传递给一个合并函数 `BiFunction`,以产生新的 `CompletableFuture`。
```java
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");
CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
```
- `thenAcceptBoth`: 类似于 `thenCombine`,但是不会返回任何值。它用于消费两个 `CompletableFuture` 的结果。
0
0