7

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

此方法的调用者还添加了另一个带有thenAccept. 显然,这可以通过多个链接调用进行。

调用CompletionStage返回的顺序是什么?thenAccept是否保证是添加它们的顺序?如果不是,如何保证它们按添加顺序执行?

PS:我是根据我自己的经验CompletableFuture和这篇文章问这个的

4

1 回答 1

9

您正在通过链接完成阶段的依赖关系来建模它们。如果你将两个动作AB另一个动作链接起来C,你定义了关系A → CB → C,但没有关系A和之间B,因此,它们之间没有关系,包括没有排序关系,换句话说,你甚至不能假设一个会一个接一个地跑,例如

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();

在这里,第二个消费者被链接到baseand next,以接收来自 的结果base,但取决于next' 的完成(如果没有要传递的结果,您通常不需要它——也许您想重新考虑您的设计,如果您有这样的一个场景)。

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

于 2016-06-20T09:58:23.263 回答