所以我有一个返回CompletableFuture
的方法。返回之前,此方法添加一个带有thenAccept
的块,该块在CompletableFuture
完成后执行。
此方法的调用者还添加了另一个带有thenAccept
的块。显然,这可以通过多个链接调用来进行。CompletionStage
调用返回的thenAccept
以什么顺序执行?是否保证是它们的添加顺序?如果没有,如何保证它们按添加的顺序执行?
PS:我是根据自己对CompletableFuture
和article的经验问这个问题
最佳答案
您正在通过链接完成阶段的依赖关系。如果将两个 Action A
和B
链接到另一个 Action 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
和next
,以从base
接收结果,但是要取决于next
的完成情况(如果没有结果通过,通常不需要这样做-也许您想重新考虑设计,如果您有这种情况)。或者,您可以将第一个
Consumer
转换为通过该值的Function
,因此您可以通过thenApply
链接它,以允许将另一个thenAccept
阶段链接到该值。