【问题标题】:CompletableFuture: How to apply a function to multiple CompletableFutures?CompletableFuture:如何将一个函数应用于多个 CompletableFuture?
【发布时间】:2017-03-22 09:01:05
【问题描述】:

假设我有 3 个下载,框架为可完成的期货:

    CompletableFuture<Doc> dl1 = CompletableFuture.supplyAsync(() -> download("file1"));
    CompletableFuture<Doc> dl2 = CompletableFuture.supplyAsync(() -> download("file2"));
    CompletableFuture<Doc> dl3 = CompletableFuture.supplyAsync(() -> download("file3"));

那么所有这些都需要以相同的方式处理

    CompletableFuture<String> s1 = dl1.thenApply(Doc::getFilename);
    CompletableFuture<String> s2 = dl2.thenApply(Doc::getFilename);
    CompletableFuture<String> s3 = dl3.thenApply(Doc::getFilename);

您可以想象要同时应用多个函数。

根据 DRY 原则,这个例子似乎不合适。因此,我正在寻找一种解决方案,以仅定义 1 个并行执行 3 次的工作流。

如何做到这一点?

我试过allOf,但有两个问题1)它开始阻塞,2)返回类型只能run填充而不是处理它。

【问题讨论】:

  • 声明新方法首先调用下载,然后调用getFilename
  • 您是否考虑过将文件放入列表中然后对其进行迭代?

标签: java concurrency java-8 java.util.concurrent completable-future


【解决方案1】:
Stream.of("file1", "file2", "file3") // or your input in any other format, that can easily be transformed to a stream...
      // .parallel() // well... depends...
      .map(s -> CompletableFuture.supplyAsync(() -> download(s)))
      .map(dl -> dl.thenApply(Doc::getFilename))
      .map(CompletableFuture::join) // if you want to have all the results collected
      .collect(Collectors.toList());

当然也可以组合两个map-calls。但至少你不会把所有东西都写 x 次......如果你不喜欢 List 的集合,你也可以在上面调用其他东西,例如.forEach(System.out::println).forEach 的好处是,一旦响应可用,就会调用消费者。

或者经典:只需使用循环和列表/数组作为输入,但与流相比,您可能需要注意更多

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多