所以我有一个返回CompletableFuture
的方法。在返回之前,此方法会添加一个thenAccept
的块,该块在CompletableFuture
完成后执行。
此方法的调用者还添加了另一个thenAccept
块。显然,这可以继续多个链式调用。
执行CompletionStage
调用返回的thenAccept
的顺序是什么?是否保证是添加它们的顺序?如果没有,如何保证它们按照添加顺序执行?
PS:我根据自己对CompletableFuture
和article
答案 0 :(得分:7)
您通过链接来建模完成阶段的依赖关系。如果您将两个操作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
和next
,以便从base
接收结果,但是依赖于next
的完成(您通常不会这样做)如果没有结果可以通过 - 如果您有这样的情况,也许您想重新考虑您的设计。)
或者,您可以将第一个Consumer
转换为通过该值的Function
,以便您可以通过thenApply
将其链接,以允许链接另一个thenAccept
阶段它。