引言
在现代软件开发中,异步编程已经成为处理高并发和高性能应用的重要技术。Java 8 引入了 CompletableFuture
,这是一个强大的异步编程工具,可以帮助开发者更轻松地处理多线程编程中的异步任务。本文将详细介绍 CompletableFuture
的基本概念、常用方法和如何进行异步编排,帮助你在实际项目中更好地利用这一工具。
什么是 CompletableFuture?
CompletableFuture
是 java.util.concurrent
包下的一个类,实现了 Future
和 CompletionStage
接口。它提供了一种非常灵活的方式来处理异步任务,支持链式调用、组合多个异步任务、处理异步任务的结果和异常等多种操作。
基本概念
- Future:一个代表异步计算结果的接口。它提供了一个方法
get()
来获取计算结果,如果计算结果尚未完成,调用get()
会阻塞。 - CompletionStage:一个表示异步计算阶段的接口。它允许你定义后续的计算阶段,这些阶段可以是另一个异步任务,也可以是同步任务。
- CompletableFuture:一个具体的
Future
和CompletionStage
实现类,提供了丰富的异步编程方法。
创建 CompletableFuture
CompletableFuture
提供了多种创建方法,可以用于启动异步任务。
1. 使用 runAsync
和 supplyAsync
runAsync(Runnable)
:用于创建一个不返回结果的异步任务。supplyAsync(Supplier<T>)
:用于创建一个返回结果的异步任务。
// 不返回结果的异步任务
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
System.out.println("Running async task without result");
});
// 返回结果的异步任务
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
return "Hello, CompletableFuture!";
});
2. 使用 complete
方法
如果你已经有一个结果,可以直接完成 CompletableFuture
。
CompletableFuture<String> future3 = new CompletableFuture<>();
future3.complete("Task completed immediately");
异步任务的链式调用
CompletableFuture
支持链式调用,可以将多个异步任务组合成一个任务流。
1. thenApply
:处理结果
thenApply
方法用于对前一个任务的结果进行处理,并返回一个新的结果。
CompletableFuture<String> future4 = future2.thenApply(result -> {
return result.toUpperCase();
});
future4.thenAccept(System.out::println); // 输出: HELLO, COMPLETABLEFUTURE!
2. thenAccept
:消费结果
thenAccept
方法用于消费前一个任务的结果,不返回新的结果。
future2.thenAccept(result -> {
System.out.println("Result: " + result);
});

3. thenRun
:执行后续动作
thenRun
方法用于在前一个任务完成后执行一个无参数的动作,不返回新的结果。
future2.thenRun(() -> {
System.out.println("Task completed");
});
组合多个异步任务
CompletableFuture
还提供了多种方法来组合多个异步任务。
1. thenCompose
:组合两个异步任务
thenCompose
方法用于将两个异步任务组合在一起,前一个任务的结果作为后一个任务的输入。
CompletableFuture<String> future5 = future2.thenCompose(result -> {
return CompletableFuture.supplyAsync(() -> {
return result + " - Extended";
});
});
future5.thenAccept(System.out::println); // 输出: Hello, CompletableFuture! - Extended
2. thenCombine
:组合两个异步任务
thenCombine
方法用于将两个异步任务的结果组合在一起,执行一个共同的处理函数。
CompletableFuture<String> future6 = CompletableFuture.supplyAsync(() -> {
return "CompletableFuture-1";
});
CompletableFuture<String> future7 = CompletableFuture.supplyAsync(() -> {
return "CompletableFuture-2";
});
CompletableFuture<String> future8 = future6.thenCombine(future7, (result1, result2) -> {
return result1 + " " + result2;
});
future8.thenAccept(System.out::println); // 输出: CompletableFuture-1 CompletableFuture-2
处理异常
在异步任务中,处理异常是非常重要的。CompletableFuture
提供了 exceptionally
和 handle
方法来处理异常。
1. exceptionally
:处理异常
exceptionally
方法用于处理前一个任务中抛出的异常,并返回一个默认的结果。
CompletableFuture<String> future9 = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("Task failed");
}).exceptionally(ex -> {
return "Fallback result: " + ex.getMessage();
});
future9.thenAccept(System.out::println); // 输出: Fallback result: Task failed
2. handle
:处理结果和异常
handle
方法用于处理前一个任务的结果或异常,并返回一个新的结果。
CompletableFuture<String> future10 = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("Task failed");
}).handle((result, ex) -> {
if (ex != null) {
return "Handle fallback: " + ex.getMessage();
} else {
return "Result: " + result;
}
});
future10.thenAccept(System.out::println); // 输出: Handle fallback: Task failed
异步任务的并行执行
CompletableFuture
还支持并行执行多个任务,并在所有任务完成后进行处理。
1. allOf
:等待所有任务完成
allOf
方法用于等待多个 CompletableFuture
对象完成,但不返回结果。
CompletableFuture<String> future11 = CompletableFuture.supplyAsync(() -> {
return "Task 1";
});
CompletableFuture<String> future12 = CompletableFuture.supplyAsync(() -> {
return "Task 2";
});
CompletableFuture<String> future13 = CompletableFuture.supplyAsync(() -> {
return "Task 3";
});
CompletableFuture<Void> allFutures = CompletableFuture.allOf(future11, future12, future13);
allFutures.thenRun(() -> {
System.out.println("All tasks are completed");
});
2. anyOf
:等待任意一个任务完成
anyOf
方法用于等待多个 CompletableFuture
对象中的任意一个完成,并返回第一个完成的任务的结果。
CompletableFuture<String> future14 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Task 1";
});
CompletableFuture<String> future15 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Task 2";
});
CompletableFuture<String> anyFuture = CompletableFuture.anyOf(future14, future15);
anyFuture.thenAccept(result -> {
System.out.println("First completed task: " + result);
}); // 输出: First completed task: Task 2
阻塞和非阻塞操作
CompletableFuture
支持阻塞和非阻塞操作,可以根据需要选择合适的方式。
1. 阻塞操作:get
方法
get
方法会阻塞当前线程,直到异步任务完成并返回结果。
try {
String result = future2.get();
System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
2. 非阻塞操作:thenApply
、thenAccept
和 thenRun
这些方法是非阻塞的,它们会在前一个任务完成后执行后续操作。
总结
CompletableFuture
是 Java 8 引入的一个强大工具,用于处理异步任务的编排。通过链式调用、组合多个异步任务以及异常处理等功能,CompletableFuture
能够帮助开发者更轻松地编写高性能、高并发的异步代码。
希望你喜欢这篇文章!请点关注和收藏吧。你的关注和收藏会是我努力更新的动力,祝关注和收藏的帅哥美女们今年都能暴富。如果有更多问题,欢迎随时提问