处理大量CompletableFuture时的参数传递
当你有大量CompletableFuture
需要传递给allOf
时,不需要一个一个列出来。以下是几种更优雅的处理方式:
1. 使用数组或集合传递
// 创建一个List保存所有future
List<CompletableFuture<String>> futures = new ArrayList<>();
// 批量添加future
for (int i = 0; i < 100; i++) {
final int taskId = i;
futures.add(CompletableFuture.supplyAsync(() -> "任务" + taskId + "的结果"));
}
// 转换为数组传递给allOf
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
futures.toArray(new CompletableFuture[0])
);
2. 使用Stream API创建
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
IntStream.range(0, 100)
.mapToObj(i -> CompletableFuture.supplyAsync(() -> "任务" + i + "的结果"))
.toArray(CompletableFuture[]::new)
);
3. 批量处理并收集结果
List<CompletableFuture<String>> futures = IntStream.range(0, 100)
.mapToObj(i -> CompletableFuture.supplyAsync(() -> {
// 模拟耗时操作
try { Thread.sleep(100); } catch (InterruptedException e) {}
return "任务" + i + "的结果";
}))
.collect(Collectors.toList());
CompletableFuture<Void> allDone = CompletableFuture.allOf(
futures.toArray(new CompletableFuture[0])
);
// 等待所有完成并收集结果
CompletableFuture<List<String>> allResults = allDone.thenApply(v ->
futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList())
);
// 获取最终结果
List<String> results = allResults.join();
4. 使用辅助方法
如果需要频繁使用,可以创建一个工具方法:
public static <T> CompletableFuture<List<T>> allOfList(List<CompletableFuture<T>> futures) {
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.thenApply(v -> futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList()));
}
// 使用示例
List<CompletableFuture<String>> futures = ...;
CompletableFuture<List<String>> combinedFuture = allOfList(futures);
List<String> results = combinedFuture.join();
5. 并行流+CompletableFuture结合
List<String> results = IntStream.range(0, 100)
.parallel()
.mapToObj(i -> {
// 模拟异步任务
return CompletableFuture.supplyAsync(() -> "结果" + i);
})
.collect(Collectors.toList())
.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
注意事项
- 大量异步任务时要注意线程池资源管理,避免创建过多线程
- 考虑使用自定义的线程池而不是默认的ForkJoinPool
ExecutorService executor = Executors.newFixedThreadPool(20); CompletableFuture.supplyAsync(() -> "...", executor);
- 如果任务数量极大,可以考虑分批处理
这些方法可以让你优雅地处理任意数量的CompletableFuture
,而不需要手动列出每一个。