CompletableFuture 是 Java 中提供的用于异步编程的类,位于 java.util.concurrent 包中。它允许你以非阻塞的方式编写并发代码,支持链式调用,并且提供了处理任务完成后的各种回调方法。以下是 CompletableFuture 的详细用法和常见场景。
1. 创建 CompletableFuture 对象
-
手动完成
CompletableFuture<String> future = new CompletableFuture<>(); // 在其他地方手动完成 future.complete("Result"); -
异步任务 使用
supplyAsync()创建一个异步任务,该方法接收Supplier,返回结果。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // 模拟耗时操作 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return "Hello, CompletableFuture!"; });
2. 链式调用
CompletableFuture 允许将多个异步操作链接在一起,按顺序执行。
-
thenApply 在当前任务执行完成后执行一个函数,处理返回值并返回新的
CompletableFuture。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenApply(result -> result + " World"); -
thenAccept 和
thenApply类似,但不返回值,只对结果进行处理。CompletableFuture.supplyAsync(() -> "Hello") .thenAccept(result -> System.out.println("Result: " + result));
-
thenRun 不关心任务的返回结果,只在任务完成后执行动作。
CompletableFuture.supplyAsync(() -> "Hello") .thenRun(() -> System.out.println("Task completed!"));
3. 异常处理
-
exceptionally 当异步操作抛出异常时,可以使用
exceptionally进行处理并提供默认值。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { if (Math.random() > 0.5) { throw new RuntimeException("Something went wrong!"); } return "Success"; }).exceptionally(ex -> "Default Value"); -
handle
handle方法无论任务是否异常都会执行,并且可以访问到异常对象。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { if (Math.random() > 0.5) { throw new RuntimeException("Error occurred!"); } return "Success"; }).handle((result, ex) -> { if (ex != null) { return "Error handled"; } return result; });
4. 组合多个 CompletableFuture
-
thenCombine 将两个
CompletableFuture的结果组合。CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World"); CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (f1, f2) -> f1 + " " + f2); -
allOf 等待所有
CompletableFuture完成。CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Task 1"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Task 2"); CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2); allOfFuture.join(); // 阻塞直到所有任务完成 -
anyOf 只要任意一个
CompletableFuture完成即可返回结果。CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Task 1"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Task 2"); CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(future1, future2);
5. 超时处理
可以设置任务的超时,使用 orTimeout 和 completeOnTimeout 方法。
-
orTimeout 如果超过指定时间没有完成,将抛出
TimeoutException。CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } return "Task Result"; }).orTimeout(3, TimeUnit.SECONDS); -
completeOnTimeout 如果任务超时,可以返回默认值而不抛出异常。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } return "Task Result"; }).completeOnTimeout("Default Result", 3, TimeUnit.SECONDS);
6. 阻塞获取结果
-
get()
和
join()
get()方法抛出受检异常,而
join()方法则不抛出受检异常。
String result = future.get(); // 阻塞,等待结果 String result = future.join(); // 也是阻塞,但不会抛出受检异常
7. 取消任务
可以使用 cancel() 方法取消一个正在运行的任务。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Task Result";
});
future.cancel(true); // 取消任务