所以我有一个返回CompletableFuture的方法。返回之前,此方法添加一个带有thenAccept的块,该块在CompletableFuture完成后执行。

此方法的调用者还添加了另一个带有thenAccept的块。显然,这可以通过多个链接调用来进行。
CompletionStage调用返回的thenAccept以什么顺序执行?是否保证是它们的添加顺序?如果没有,如何保证它们按添加的顺序执行?

PS:我是根据自己对CompletableFuturearticle的经验问这个问题

最佳答案

您正在通过链接完成阶段的依赖关系。如果将两个 Action AB链接到另一个 Action C,则定义关系A → CB → C,但是AB之间没有关系,因此,它们之间没有关系,包括没有排序关系,换句话说,您可以甚至都不认为一个人会追赶另一个人,即

CompletableFuture<String> base=CompletableFuture.supplyAsync(() -> {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
    return "source";
});
base.thenAccept(s -> {
    System.out.println("entered first consumer in "+Thread.currentThread());
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    System.out.println("leaving first consumer");
});
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
base.thenAccept(s -> {
    System.out.println("entered second consumer in "+Thread.currentThread());
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    System.out.println("leaving second consumer");
});

很有可能会打印类似

entered first consumer in Thread[ForkJoinPool.commonPool-worker-1,5,main]
entered second consumer in Thread[main,5,main]
leaving second consumer
leaving first consumer

当然,这没有任何保证。

为了加强两个使用者之间的依赖性,您必须将它们适当地链接起来,例如
CompletableFuture<String> base=CompletableFuture.supplyAsync(() -> {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
    return "source";
});
CompletableFuture<Void> next = base.thenAccept(s -> {
    System.out.println("entered first consumer in "+Thread.currentThread());
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    System.out.println("leaving first consumer");
});
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
base.thenAcceptBoth(next, (s,ignored) -> {
    System.out.println("entered second consumer in "+Thread.currentThread());
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    System.out.println("leaving second consumer");
}).join();

在这里,第二个使用者被链接到basenext,以从base接收结果,但是要取决于next的完成情况(如果没有结果通过,通常不需要这样做-也许您想重新考虑设计,如果您有这种情况)。

或者,您可以将第一个Consumer转换为通过该值的Function,因此您可以通过thenApply链接它,以允许将另一个thenAccept阶段链接到该值。

09-28 06:24