CompletableFuture
是 Java 8 引入的一个非常强大的类,用于异步编程,它支持非阻塞的异步执行、组合多个异步操作以及处理异常等。通过 CompletableFuture
,你可以更方便地编写并发和异步代码,避免回调地狱。
1. 创建 CompletableFuture
CompletableFuture
可以通过多种方式创建:
使用静态方法创建
supplyAsync
:执行一个异步任务,返回一个结果。runAsync
:执行一个异步任务,不返回结果。
// 1. 使用 supplyAsync 创建 CompletableFuture
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// 模拟耗时任务
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
return 42; // 返回结果
});
// 2. 使用 runAsync 创建 CompletableFuture
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
// 执行没有返回值的异步任务
try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("任务完成");
});
2. 获取结果
你可以使用 get()
或 join()
方法来阻塞获取异步任务的结果:
// 获取结果,get() 是阻塞方法
try {
Integer result = future.get(); // 阻塞直到获取结果
System.out.println("结果是:" + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 或者使用 join()(类似 get,但不会抛出异常)
Integer result2 = future.join();
System.out.println("结果是:" + result2);
3. 处理异步结果
CompletableFuture
提供了多种方法来处理异步任务的结果,包括 thenApply
、thenAccept
和 thenRun
等。
thenApply
:处理返回结果并继续异步执行。thenAccept
:处理返回结果并不继续后续操作。thenRun
:不处理返回值,只执行后续操作。
// 1. 使用 thenApply 处理异步结果并返回新的结果
CompletableFuture<Integer> transformedFuture = future.thenApply(result -> {
return result * 2; // 将结果乘以 2
});
// 2. 使用 thenAccept 只消费结果,不返回
future.thenAccept(result -> {
System.out.println("处理结果:" + result);
});
// 3. 使用 thenRun 只执行副作用任务
future.thenRun(() -> {
System.out.println("任务完成后执行的操作");
});
4. 异常处理
CompletableFuture
还提供了异常处理的方法 exceptionally
和 handle
,当任务执行失败时,可以捕获异常并进行处理。
// 异常处理
CompletableFuture<Integer> exceptionFuture = future.exceptionally(ex -> {
System.out.println("发生异常:" + ex.getMessage());
return -1; // 返回一个默认值
});
handle
方法不仅能处理正常结果,还能处理异常,并返回一个结果。
CompletableFuture<Integer> handledFuture = future.handle((result, ex) -> {
if (ex != null) {
System.out.println("发生异常:" + ex.getMessage());
return -1;
}
return result * 2;
});
5. 组合多个异步任务
CompletableFuture
可以将多个异步任务链式组合执行,包括 thenCombine
、thenCompose
和 allOf
等方法。
thenCombine
:组合两个独立的任务的结果
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (result1, result2) -> {
return result1 + result2; // 合并两个结果
});
thenCompose
:链式组合任务,适用于需要使用前一个结果来启动后一个任务的情况
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> composedFuture = future.thenCompose(result -> {
// 将第一个结果用于下一个任务
return CompletableFuture.supplyAsync(() -> result * 2);
});
allOf
:等待多个异步任务完成
CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> 1);
CompletableFuture<Void> future2 = CompletableFuture.supplyAsync(() -> 2);
CompletableFuture<Void> future3 = CompletableFuture.supplyAsync(() -> 3);
CompletableFuture<Void> allOf = CompletableFuture.allOf(future1, future2, future3);
allOf.join(); // 等待所有任务完成
System.out.println("所有任务完成");
anyOf
:等待任意一个异步任务完成
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2, future3);
anyOf.join(); // 等待任意一个任务完成
System.out.println("至少有一个任务完成");
6. 取消任务
如果异步任务在执行过程中需要取消,可以调用 cancel
方法。
future.cancel(true); // true 表示中断正在执行的任务
7. 完整示例
import java.util.concurrent.*;
public class CompletableFutureExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 异步任务1
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
// 异步任务2
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 20;
});
// 结果合并
CompletableFuture<Integer> combined = future1.thenCombine(future2, (result1, result2) -> result1 + result2);
// 获取最终结果
Integer result = combined.get();
System.out.println("最终结果: " + result); // 输出 30
// 等待所有任务完成
CompletableFuture.allOf(future1, future2).join();
}
}
总结
方法名称 | 描述 | 返回类型 |
---|---|---|
supplyAsync(Supplier<T> supplier) | 异步执行任务并返回一个结果。 | CompletableFuture<T> |
runAsync(Runnable runnable) | 异步执行任务,但没有返回值。 | CompletableFuture<Void> |
get() | 获取异步任务的结果,阻塞直到任务完成。 | T |
join() | 获取异步任务的结果,阻塞直到任务完成,类似 get() ,但不会抛出异常。 | T |
thenApply(Function<T, U> fn) | 任务完成后,处理结果并返回新结果。 | CompletableFuture<U> |
thenAccept(Consumer<T> action) | 任务完成后,消费结果,不返回新结果。 | CompletableFuture<Void> |
thenRun(Runnable action) | 任务完成后,执行某个副作用操作,不处理返回值。 | CompletableFuture<Void> |
exceptionally(Function<Throwable, ? extends T> fn) | 异常处理,当任务抛出异常时执行给定的操作。 | CompletableFuture<T> |
handle(BiFunction<T, Throwable, ? extends T> fn) | 任务完成后,无论成功或失败都会执行指定的操作。 | CompletableFuture<T> |
thenCombine(CompletableFuture<U> other, BiFunction<T, U, V> fn) | 合并两个独立的异步任务的结果。 | CompletableFuture<V> |
thenCompose(Function<T, CompletableFuture<U>> fn) | 链式组合任务,前一个任务的结果会作为输入传给下一个任务。 | CompletableFuture<U> |
allOf(CompletableFuture<?>... futures) | 等待多个异步任务完成,返回 Void 。 | CompletableFuture<Void> |
anyOf(CompletableFuture<?>... futures) | 等待任意一个异步任务完成,返回该任务的结果。 | CompletableFuture<Object> |
cancel(boolean mayInterruptIfRunning) | 取消异步任务。 | boolean |
complete(T value) | 手动完成 CompletableFuture ,即设置任务的完成结果。 | void |
isCompletedExceptionally() | 判断 CompletableFuture 是否由于异常完成。 | boolean |
isDone() | 判断任务是否完成,无论是正常完成还是异常完成。 | boolean |
getNow(T valueIfAbsent) | 获取结果,如果尚未完成,则返回默认值。 | T |