代码之家  ›  专栏  ›  技术社区  ›  maxpovver

将多个复杂未来应用于另一个复杂未来结果的最佳方法是什么?

  •  1
  • maxpovver  · 技术社区  · 6 年前

    我们来举个例子: 我们有四种方法:

    CompletableFututre<Void> loadAndApply(SomeObject someObject);
    CompletableFuture<SomeData> loadData();
    A processA(SomeData data);
    B processB(SomeData data);
    

    loadAndApply 结合所有其他方法。 loadData 获取长时间的数据。然后我们开始 someObject.A 至运行结果 processA(data) 和设置 someObject.B 至运行结果 processB(data) 我们不能两者都适用 processA processB 同时因为 加工 只能运行 swingExecutor 进程B 只能在上运行 backgroundExecutor .

    所以我的问题是:我们能不能以一种好看的方式把所有这些方法连接起来?

    目前我是这样启动它们的:

    CompletableFututre<Void> loadAndApply(SomeObject someObject) {
        return loadData()
          .thenApplyAsync(data -> { someObject.setA(processA(data)); return data; }, swingExecutor)
          .thenAcceptAsync(data -> someObject.setB(processB(data)), backgroundExecutor);
    }
    

    有什么比这更好的方法吗 applyAsync 这实际上并没有在给定的对象上应用任何东西,只是在下一个未来返回它?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Slaw    6 年前

    您可以使用 CompletionStage.thenCompose(Function) CompletableFuture.allOf(CompletableFuture...) . 的通用签名 Function 使用人 thenCompose 是: Function<? super T, ? extends CompletionStage<U>> .

    public CompletableFuture<Void> loadAndApply(SomeObject object) {
      return loadData().thenCompose(data ->
          CompletableFuture.allOf(
              CompletableFuture.runAsync(() -> object.setA(processA(data)), swingExecutor),
              CompletableFuture.runAsync(() -> object.setB(processB(data)), backgroundExecutor)
          ) // End of "allOf"
      ); // End of "thenCompose"
    } // End of "loadAndApply"
    

    这有一个额外的好处。在代码中,您当前使用的 thenAcceptAsync 舞台必须等待 thenApplyAsync 在执行前完成的阶段。当使用上述两者时 setA setB 将在各自的执行者中并发运行。

    为了方便起见,这是JavaDoc allOf :

    返回一个新的completeTableFuture,当所有 给定完成的Futures完成。如果给定 可完成期货异常完成,然后返回 CompleteTableFuture也会这样做,并保留CompletionException 这一例外是其原因。否则,如果有的话, 给定的可完成期货不反映在返回的 但可以通过检查来获得 个别地。如果没有提供完整的Futures,则返回 CompleteTableFuture已完成,值为空。

    这种方法的应用之一是等待集合的完成。 在继续一个项目之前,独立完成的期货,如: completeTableFuture.allof(c1,c2,c3).join();。

    …还有JavaDoc 然后合成 :

    返回与以下值相同的新CompletionStage 给定函数返回的CompletionStage。

    当此阶段正常完成时,用 这个阶段的结果作为论点,返回另一个 完成阶段。当该阶段正常完成时, 此方法返回的CompletionStage使用相同的 价值。

    为确保进度,所提供的函数必须最终 结果完成。

    此方法类似于可选的.flatmap和stream.flatmap。

    有关包含异常的规则,请参阅CompletionStage文档 完成。

    注: CompletableFuture ,实现 CompletionStage ,覆盖 然后合成 但使返回类型更具体(返回 复杂的未来 而不是 完成阶段 ) .