多线程——处理大量CompletableFuture时的参数传递

处理大量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());

注意事项

  1. 大量异步任务时要注意线程池资源管理,避免创建过多线程
  2. 考虑使用自定义的线程池而不是默认的ForkJoinPool
    ExecutorService executor = Executors.newFixedThreadPool(20);
    CompletableFuture.supplyAsync(() -> "...", executor);
    
  3. 如果任务数量极大,可以考虑分批处理

这些方法可以让你优雅地处理任意数量的CompletableFuture,而不需要手动列出每一个。

### Java CompletableFuture 源码解析 `CompletableFuture` 是 Java 8 引入的一个强大工具,用于支持异步编程和回调机制。它是 `Future` 接口的扩展版本,提供了更丰富的功能来简化复杂的异步操作链式调用。 #### 1. 基本结构与设计思路 `CompletableFuture` 的核心设计理念基于状态机模型[^3]。它的内部维护了一个复杂的状态转换逻辑,允许开发者通过一系列方法(如 `supplyAsync`, `thenApply`, `whenComplete` 等)构建异步任务流水线。这些方法本质上是对底层状态的变化进行监听并触发相应的动作。 以下是其主要组成部分: - **内部类**:`CompletableFuture` 定义了许多嵌套类,比如 `UniCompletion`, `BiCompletion` 和 `AsynchronousCompletionTask` 等,用来管理不同类型的依赖关系。 - **原子变量**:利用 `AtomicReferenceFieldUpdater` 或者类似的低级同步原语确保多线程环境下的安全性。 - **完成器 (Completor)** :当某个阶段的任务完成后,会通知后续阶段继续执行。 #### 2. 关键方法分析 ##### a. 创建实例 可以通过静态工厂方法创建新的未完成实例或者已经完成了计算结果的实例: ```java // 返回一个新的已完成的 CompletableFuture 对象 static <U> CompletableFuture<U> completedFuture(U value); ``` 此方法直接返回带有指定值的结果对象而无需实际运行任何异步任务[^4]。 ##### b. 提交任务 提交一个供给型任务给默认 ForkJoinPool 执行,并返回代表该未来结果的新 CompletableFuture 实例: ```java public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier); ``` 如果希望自定义 Executor,则可以使用重载版函数传递第二个参数作为定制化的线程池[^1]: ```java public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor); ``` ##### c. 链接下游处理器 一旦前序步骤结束就可以无缝衔接下一个处理单元形成完整的数据流管道图谱。例如下面这段代码展示了如何串联两个独立的操作序列: ```java CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // Task A: Simulate some work... return "Result from TaskA"; }).thenApply(resultFromPreviousStep -> { // Task B: Process the result of previous step. String processedData = process(resultFromPreviousStep); return processedData; }); ``` 这里 `.thenApply()` 方法接收的是 Function 类型泛型参数形式化表达映射变换规则从而实现从输入到输出之间的转化过程。 #### 3. 并发控制细节 为了提高性能表现以及减少不必要的上下文切换开销,在某些特定场景下可能会采用 inline 方式即求解而不是真正启动新线程去完成整个流程。这种行为取决于当前所处模式(`mode`)设置情况——即是否处于 nested 模式之下[^5]。 具体来说,当检测到存在可用资源便会尝试立即履行承诺;反之则遵循常规调度策略安排至适当位置等待机成熟后再予以兑现。 --- ### 示例代码展示 以下是一个综合运用上述知识点的例子演示了如何组合多个异步操作最终达成目标效果的同保持良好的可读性和模块划分清晰度: ```java import java.util.concurrent.CompletableFuture; public class CompletableFutureExample { public static void main(String[] args) throws Exception { CompletableFuture<Integer> cf = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(100); } catch (InterruptedException e) {} System.out.println("Supplying..."); return 123; }).thenApply(i -> { System.out.println("Applying transformation..."); return i * 2; }); Integer result = cf.join(); // Blocks until complete System.out.println("Final Result: " + result); } } ``` 在此程序片段里我们首先发起了一项耗较长的基础服务请求随后对其响应内容加以进一步加工最后打印出总的运算成果。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值