所以我有一个返回CompletableFuture
. 在返回之前,此方法会添加一个thenAccept
在完成后执行的块CompletableFuture
。
此方法的调用者还添加了另一个带有thenAccept
. 显然,这可以通过多个链接调用进行。
调用CompletionStage
返回的顺序是什么?thenAccept
是否保证是添加它们的顺序?如果不是,如何保证它们按添加顺序执行?
PS:我是根据我自己的经验CompletableFuture
和这篇文章问这个的
所以我有一个返回CompletableFuture
. 在返回之前,此方法会添加一个thenAccept
在完成后执行的块CompletableFuture
。
此方法的调用者还添加了另一个带有thenAccept
. 显然,这可以通过多个链接调用进行。
调用CompletionStage
返回的顺序是什么?thenAccept
是否保证是添加它们的顺序?如果不是,如何保证它们按添加顺序执行?
PS:我是根据我自己的经验CompletableFuture
和这篇文章问这个的
您正在通过链接完成阶段的依赖关系来建模它们。如果你将两个动作A
和B
另一个动作链接起来C
,你定义了关系A → C
和B → 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();
在这里,第二个消费者被链接到base
and next
,以接收来自 的结果base
,但取决于next
' 的完成(如果没有要传递的结果,您通常不需要它——也许您想重新考虑您的设计,如果您有这样的一个场景)。
或者,您可以将第Consumer
一个转换为Function
通过该值的 a,因此您可以通过thenApply
, 链接它,以允许将另一个thenAccept
阶段链接到它。