目录
[1.1 异步编程](#1.1 异步编程)
[1.2 CompletableFuture简介](#1.2 CompletableFuture简介)
[2.1 创建CompletableFuture对象](#2.1 创建CompletableFuture对象)
[2.2 手动完成CompletableFuture](#2.2 手动完成CompletableFuture)
[2.3 异常完成CompletableFuture](#2.3 异常完成CompletableFuture)
[3.1 异步任务的执行](#3.1 异步任务的执行)
[3.2 处理计算结果](#3.2 处理计算结果)
[4.1 thenCombine](#4.1 thenCombine)
[4.2 thenCompose](#4.2 thenCompose)
[4.3 allOf和anyOf](#4.3 allOf和anyOf)
[5.1 handle](#5.1 handle)
[5.2 exceptionally](#5.2 exceptionally)
[6.1 自定义执行器](#6.1 自定义执行器)
[6.2 超时控制](#6.2 超时控制)
[7.1 需求描述](#7.1 需求描述)
[7.2 代码实现](#7.2 代码实现)
Java的CompletableFuture
是Java 8中引入的一个功能强大的类,用于处理异步编程。它不仅提供了一种方式来表示异步计算,还提供了丰富的API来进行复杂的异步编排和处理。本文将详细讲解CompletableFuture
的基本概念、使用方法以及一些高级特性,并结合实例代码进行说明。
一、基本概念
1.1 异步编程
异步编程是一种并发编程的形式,通过非阻塞方式执行任务。传统的同步编程中,任务必须按顺序执行,每个任务必须等待前一个任务完成。然而,在异步编程中,任务可以在后台执行,主线程无需等待任务完成,因而可以继续处理其他任务。这种方式在提高程序响应速度和资源利用率方面有很大优势。
1.2 CompletableFuture
简介
CompletableFuture
是Java提供的一个实现Future
接口的类,它不仅支持传统的Future
接口方法,还引入了许多新的方法来支持回调、组合、处理异常等功能。通过这些方法,开发者可以更方便地编写异步代码。
二、创建和完成CompletableFuture
2.1 创建CompletableFuture
对象
创建一个CompletableFuture
对象非常简单,可以通过以下几种方式:
-
使用
CompletableFuture
的静态工厂方法:CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello, World!");
-
使用默认构造函数创建一个空的
CompletableFuture
,然后在未来的某个时间点手动完成它:CompletableFuture<String> future = new CompletableFuture<>(); // 在其他线程或任务中完成这个future future.complete("Hello, World!");
2.2 手动完成CompletableFuture
你可以通过complete
方法手动完成一个CompletableFuture
:
CompletableFuture<String> future = new CompletableFuture<>();
future.complete("Hello, World!");
如果已经完成的CompletableFuture
再次调用complete
,将不会改变其状态。
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
提供了多种方法来处理异步任务的结果,例如:
-
thenApply
:当CompletableFuture
完成时,对其结果进行处理,并返回一个新的CompletableFuture
。 -
thenAccept
:当CompletableFuture
完成时,消费其结果,但不返回新的CompletableFuture
。 -
thenRun
:当CompletableFuture
完成时,运行一个任务,不关心其结果。
java
CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(result -> result + ", World!")
.thenAccept(System.out::println);
上述代码中,supplyAsync
方法执行异步任务并返回结果"Hello"。thenApply
方法对结果进行处理,得到"Hello, World!"。thenAccept
方法消费处理后的结果,并打印输出。
四、组合多个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 allOf
和anyOf
-
allOf
:等待所有提供的CompletableFuture
都完成。 -
anyOf
:只要任意一个CompletableFuture
完成即可。
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引入了orTimeout
和completeOnTimeout
方法:
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 需求描述
假设我们在开发一个在线购物平台,用户下单时需要进行以下操作:
-
验证用户信息。
-
检查库存。
-
处理支付。
-
生成订单。
我们希望这些操作尽可能并行执行,以提高系统的响应速度。
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
来并行执行用户验证、库存检查和支付处理。所有任务都在自定义的线程池中执行,最后通过生成订单来完成整个流程。如果在任何一个步骤中发生异常,系统会捕获并处理。