“重用”CompletableFuture是安全/良好的做法

时间:2016-08-16 13:05:56

标签: java java-8 completable-future

在尝试CompletableFuture时,我想知道给定的代码是否安全。

    CompletableFuture<Integer> foo = CompletableFuture.supplyAsync(() -> 42);

    foo.thenApply((bar) -> {
        System.out.println("bar " + bar);
        return bar;
    })
    .acceptEither(foo.thenApply((baz) -> {
        System.out.println("baz " + baz);
        return baz;
    }),
    (z) -> System.out.println("finished processing of " + z));

它有效,打印

bar 42
baz 42
finished processing of 42

thenApply的给定实例上多次调用CompletableFuture或其他方法是否安全/好主意?

1 个答案:

答案 0 :(得分:6)

您所描述的不是CompleteableFuture的“重复使用”,因为它仍然只执行一次操作并且最多只能完成一次。

您只是注册多个依赖阶段,这完全在预见的用途范围内。在任何一点上,文献都没有提出依赖阶段必须形成一个单一的线性链。用例已由interface CompletionStage<T>

描述
  

可能异步计算的一个阶段,它在另一个CompletionStage完成时执行操作或计算值。阶段在计算终止时完成,但这可能反过来触发其他依赖阶段。

请注意使用“其他依赖阶段”而不是“另一个依赖阶段”。在涉及阶段时,整个文档始终使用复数。这也适用于CompletableFuture<T>实现类的文档。

毕竟,如果你有两个动作一个 b ,它们彼此之间没有依赖关系但只依赖于 c ,那么有意义的是将两者都链接到 c ,而不是创建像 c a b 这样的链或 c b a ,因为后者会阻止独立操作 a b ,这是并发API的全部要点。

请注意,以这种方式对依赖项进行建模时,不会保证您显示的结果。两个打印操作“bar”和“baz”彼此之间没有依赖关系,但仅限于42值的供应商,并且计划打印“已完成处理”的操作为了完成 不是。因此,除了“bar”和“baz”输出的不确定顺序之外,您还可以看到“bar,finished processing,baz”或“baz,finished processing,bar”等日志。