CompletableFuture是 Java 8 引入的一个用于异步编程的工具类,相比于传统的Future,它具有以下优点:
一、优点
非阻塞性:
CompletableFuture允许你以异步的方式执行任务,而不会阻塞当前线程等待结果。你可以在发起一个异步任务后继续执行其他操作,然后在需要结果的时候再去获取,提高了程序的响应性和并发性。
例如,在一个 Web 应用中,当处理一个请求时,可以同时发起多个异步的数据库查询或远程服务调用,而不需要等待这些操作完成就可以先返回部分结果或进行其他处理,从而减少用户的等待时间。
丰富的操作方法:
CompletableFuture提供了大量的方法来组合、转换和处理异步任务的结果。可以方便地对多个异步任务进行编排,实现复杂的异步流程控制。
例如,可以使用thenApply方法在一个异步任务完成后对其结果进行转换,使用thenCompose方法将多个异步任务串联起来,使用allOf和anyOf方法来等待多个异步任务全部完成或其中一个完成等。
异常处理:
提供了简洁的方式来处理异步任务中的异常。可以使用exceptionally方法在异步任务出现异常时进行统一的处理,而不需要像传统的Future那样通过检查isDone和get方法的异常来处理异常情况。
例如,如果一个异步任务在执行过程中抛出了异常,可以使用exceptionally方法捕获这个异常,并返回一个默认值或者执行一些补偿操作,而不会让整个程序崩溃。
二、异步任务的编排组合
异步任务的编排组合指的是将多个异步任务按照特定的顺序和逻辑进行组合,以实现更复杂的异步操作流程。例如,可以先执行一个异步任务,然后根据其结果执行另一个异步任务,或者同时执行多个异步任务并在它们都完成后进行一些处理。
三、举例
假设我们有一个电商系统,需要从数据库中获取商品信息,然后根据商品信息从远程服务器获取商品的图片,最后将商品信息和图片展示给用户。使用CompletableFuture可以这样实现:
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
// 模拟从数据库获取商品信息
CompletableFuture<String> productInfoFuture = CompletableFuture.supplyAsync(() -> {
try {
// 模拟数据库查询耗时操作
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Product Name: Laptop, Price: $1000";
});
// 根据商品信息从远程服务器获取商品图片
CompletableFuture<String> productImageFuture = productInfoFuture.thenApplyAsync(productInfo -> {
try {
// 模拟远程服务调用耗时操作
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Product image URL: http://example.com/laptop.jpg";
});
// 当两个任务都完成后,展示商品信息和图片
CompletableFuture<Void> combinedFuture = productInfoFuture.thenCombine(productImageFuture, (productInfo, productImage) -> {
System.out.println("Product Information: " + productInfo);
System.out.println("Product Image: " + productImage);
return null;
});
// 等待所有任务完成
combinedFuture.join();
}
}
我们首先使用CompletableFuture.supplyAsync创建了一个异步任务来模拟从数据库获取商品信息。然后,使用thenApplyAsync方法根据商品信息创建了另一个异步任务来获取商品图片。最后,使用thenCombine方法将两个异步任务的结果组合起来进行展示。整个过程中,各个任务都是异步执行的,提高了程序的效率和响应性。