CompletableFuture
是 Java 8 引入的一个功能强大的并发 API,它允许你以异步的方式执行代码,并且可以方便地处理异步计算的结果。CompletableFuture
提供了丰富的方法来组合和处理异步操作。
thenApply
, thenCompose
, thenAccept
等)来组合多个异步操作。CompletableFuture
本身是一个泛型类,可以处理任何类型的结果。常见的类型包括 CompletableFuture<Void>
, CompletableFuture<Integer>
, CompletableFuture<String>
等。
适用于需要并发执行多个任务,并且需要等待所有任务完成后再进行后续处理的场景。例如,批量处理数据、并发请求多个 API 等。
假设我们有一个方法 fetchDataAsync
,它返回一个 CompletableFuture<Integer>
,表示异步获取数据的结果。我们可以使用 CompletableFuture.allOf
方法来等待所有异步操作完成,并将结果加到整型变量中。
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExample {
public static void main(String[] args) {
List<CompletableFuture<Integer>> futures = new ArrayList<>();
// 模拟多个异步任务
for (int i = 0; i < 5; i++) {
CompletableFuture<Integer> future = fetchDataAsync(i);
futures.add(future);
}
// 等待所有异步任务完成
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
futures.toArray(new CompletableFuture[0])
);
try {
allFutures.get(); // 阻塞等待所有任务完成
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 计算所有结果的总和
int sum = futures.stream()
.mapToInt(future -> {
try {
return future.get(); // 获取每个异步任务的结果
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
return 0;
}
})
.sum();
System.out.println("总和: " + sum);
}
private static CompletableFuture<Integer> fetchDataAsync(int data) {
return CompletableFuture.supplyAsync(() -> {
// 模拟异步操作,例如网络请求或数据库查询
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return data * 2;
});
}
}
问题:CompletableFuture.get()
方法会阻塞当前线程,如果异步任务执行时间过长,可能会导致性能问题。
解决方法:可以使用 CompletableFuture.join()
方法,它与 get()
方法类似,但不会抛出检查异常。此外,可以考虑使用 CompletableFuture.allOf
结合 thenApply
或 thenAccept
方法来处理所有异步任务完成后的逻辑,而不是直接阻塞等待。
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
futures.toArray(new CompletableFuture[0])
);
allFutures.thenApply(v -> {
int sum = futures.stream()
.mapToInt(future -> {
try {
return future.get();
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
return 0;
}
})
.sum();
System.out.println("总和: " + sum);
return null;
}).exceptionally(ex -> {
ex.printStackTrace();
return null;
});
这样可以避免阻塞主线程,提高程序的响应性。
领取专属 10元无门槛券
手把手带您无忧上云