CompletableFuture是Java8引入的,在Future的基础上实现了异步编排功能,并且可以使用complete方法在不同线程中通信。
Future
Future类用来表示一个异步计算的结果,可以用来获取计算的结果或者取消任务的执行。
主要方法有:
isDone():判断任务是否已经完成。
get():获取异步任务的执行结果,如果任务还没有完成则会阻塞当前线程直到任务完成。
cancel():取消异步任务的执行。
isCancelled():判断任务是否已经被取消。
运用场景:当需要处理耗时任务,我们可以将耗时任务交给子线程去异步执行,当耗时任务处理完后我们可以在主线程通过Future获取处理结果。我们可以利用future+线程池改善计算性能。
举个例子:我们需要统计多个网站内容长度,假如串行计算的话,我们的耗时就是单独计算每个网站长度所需要时间的和,但如果我们并行计算计算的话可以节省大量时间。
import java.util.concurrent.*;
//通过Future对象可以获取每个任务的执行结果(网站内容长度),最后我们将各个网站内容的长度相加,得到总的内容长度并输出。这样就实现了并行地获取多个网站内容的长度的统计。
public class FutureApplicationExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(5);
Future<Integer> future1 = executor.submit(() -> getContentLength("https://www.google.com"));
Future<Integer> future2 = executor.submit(() -> getContentLength("https://www.facebook.com"));
Future<Integer> future3 = executor.submit(() -> getContentLength("https://www.twitter.com"));
int totalLength = future1.get() + future2.get() + future3.get();
System.out.println("Total length of content: " + totalLength);
executor.shutdown();
}
private static int getContentLength(String url) {
// 发起HTTP请求获取网站内容,并返回内容长度
// 这里用休眠时间模拟HTTP请求
try {
Thread.sleep(2000); // 模拟HTTP请求
} catch (InterruptedException e) {
e.printStackTrace();
}
return url.length(); // 返回内容长度
}
}
缺点:Future只能同步(通过get方法阻塞等待结果或者isDone方法轮询查询任务是否结束)等待任务结束(或成功、或失败)才能得到结果。
CompletableFuture
Java8引入了CompletableFuture,CompletableFutrue实现了Future接口和ComletionStage接口,CompletionStage接口定义了任务编排的方法,执行某一阶段,可以向下执行后续阶段,除了拥有Future的功能以外还能实现异步编程。另外,还可以使用complete方法在不同线程中通信。
常用方法:
1. supplyAsync(): 创建一个CompletableFuture对象并异步执行一个任务,并返回任务的结果。
CompletableFuture<Integer> future
= CompletableFuture.supplyAsync(() -> 42); int result = future.get(); // result = 42
2. thenApply(): 当CompletableFuture的任务完成后,对任务的结果进行转换处理,并返回新的结果。
CompletableFuture<String> future
= CompletableFuture.supplyAsync(() -> "Hello") .thenApply(s -> s + " World");
String result = future.get(); // result = "Hello World"
3. thenCombine(): 当两个CompletableFuture都完成后,将它们的结果进行组合处理,并返回新的结果。
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (x, y) -> x + y);
int result = combinedFuture.get(); // result = 30
4. thenAccept(): 当CompletableFuture的任务完成后,对任务的结果进行消费处理,没有返回值。
CompletableFuture<Void> future =
CompletableFuture.supplyAsync(() -> "Hello")
.thenAccept(System.out::println); future.get(); // 输出 "Hello"
5. exceptionally(): 当CompletableFuture的任务执行过程中出现异常时,可以进行异常处理并返回默认值。
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 10 / 0)
.exceptionally(e -> { System.out.println("Error occurred: " + e);
return 0; // 返回默认值
});
int result = future.get(); // result = 0
6. thenCompose(): 将连续的CompletableFuture任务连接在一起,将一个任务的结果作为输入传递给另一个任务。
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 5);
CompletableFuture<Integer> future2 = future1.thenCompose(result ->
CompletableFuture.supplyAsync(() -> result * 2));
int result = future2.get(); // result = 10
7. allOf(): 该方法接受一个CompletableFuture数组作为参数,并创建一个新的CompletableFuture对象,该对象在所有输入的CompletableFuture都完成后才会完成。
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> 30);
CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2, future3);
// 等待所有CompletableFuture完成
8. anyOf(): 该方法接受一个CompletableFuture数组作为参数,并创建一个新的CompletableFuture对象,该对象在任何一个输入的CompletableFuture完成后就会完成。
anyOf(): 该方法接受一个CompletableFuture数组作为参数,并创建一个新的CompletableFuture对象,该对象在任何一个输入的CompletableFuture完成后就会完成。
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(future1, future2);
Object result = anyOfFuture.get(); // 获取第一个完成的CompletableFuture的结果
9. complete(): CompletableFuture类中的complete()方法用于手动触发CompletableFuture的计算结果。通过complete()方法,可以手动设置CompletableFuture的计算结果,而不是等待任务自动完成。这在一些特定场景下比较有用,比如与外部事件或条件相关的异步任务处理。
CompletableFuture<Integer> future = new CompletableFuture<>();
// 模拟异步任务,1秒后手动设置计算结果为42
new Thread(() -> {
try {
Thread.sleep(1000);
future.complete(42);
} catch (InterruptedException e) {
future.completeExceptionally(e);
}
}).start();
// 获取CompletableFuture的计算结果
try {
int result = future.get(); // 阻塞直到任务完成并获取结果
System.out.println("计算结果为: " + result);
} catch (Exception e) {
System.out.println("计算出错: " + e.getMessage());
}
获取异步计算的结果也非常简单,直接调用 get()
方法即可。调用 get()
方法的线程会阻塞直到 CompletableFuture
完成运算。