【问题标题】:Stop CompletableFuture chaining inside the Supplier停止供应商内部的 CompletableFuture 链接
【发布时间】:2020-01-02 06:59:49
【问题描述】:

我有这样的操作,

public void createFuture() {
    CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 5);
    future.thenApply(i -> {
        if (i == 5) {
            System.out.println("hello, i equals to 5 so expensive operations are unnecessary");
        }
        return i;
    }).thenApply(i -> {
        if (i != 5) {
            System.out.println("Expensive operation");
        }
        return i;
    }).thenApply(i -> {
        if (i != 5) {
            System.out.println("Expensive operation");
        }
        return i;
    }).thenApply(i -> {
        if (i != 5) {
            System.out.println("Expensive operation");
        }
        return i;
    }).thenApply(i -> {
        if (i != 5) {
            System.out.println("Expensive operation");
        }
        return i;
    });

}

在第一个块中,我检查了一些条件(i == 5),如果它是真的,我不需要其余的操作。我不想抛出异常来取消其余的,因为这不是特殊情况。除了将一些布尔值传递给每个操作之外,还有什么好方法吗?

【问题讨论】:

  • 您也许可以使用thenCompose 来发挥您的优势。

标签: java asynchronous java-8 java-stream completable-future


【解决方案1】:

CompletableFuture 没有支持条件语句的机制。在您的情况下,可以通过将i != 5 的所有任务提取到一个CompletableFuturethenCompose 中来简化代码。

其他解决方法是创建一个地图,对其进行过滤并使用它创建一个可完成的未来:

Map<Predicate<Integer>, Runnable> m = Map.of(
    integer -> integer == 5,
    () -> System.out.println("Task 1"),
    integer -> integer != 5,
    () -> System.out.println("Task 2"),
    integer -> integer != 5,
    () -> System.out.println("Task 3")
);
CompletableFuture[] runnables = m.entrySet().stream()
    .filter(e -> e.getKey().test(5))
    .map(Map.Entry::getValue)
    .map(CompletableFuture::runAsync)
    .toArray(CompletableFuture[]::new);
CompletableFuture composed = CompletableFuture.allOf(runnables);

在这里我正在创建一个地图Predicate -> Runnable。然后我过滤掉所有不满足谓词的对,并将可运行对象包装到CompletableFutures 中。最后composed 是一个CompletableFuture,它由所有所需的可运行文件组成。

【讨论】:

    【解决方案2】:

    CompletableFuture.thenCompose() 应该可以解决问题。

    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.CompletionStage;
    import java.util.concurrent.ExecutionException;
    
    class Scratch {
    
      public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 5);
        CompletableFuture<Integer> composed = future.thenCompose(number -> {
          if (number == 5)
            return simpleFuture(number);
          else
            return complexFuture(number);
        });
        System.out.println(composed.get());
      }
    
      private static CompletionStage<Integer> complexFuture(Integer number) {
        return CompletableFuture.completedFuture(number)
            .thenApply(i -> {
              System.out.println("I am expensive");
              return i;
            });
      }
    
      private static CompletableFuture<Integer> simpleFuture(Integer number) {
        return CompletableFuture.completedFuture(number)
            .thenApply(i -> {
              System.out.println("I am cheap");
              return i;
            });
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-04
      • 2021-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多