There is no such guaranty about the executing thread in the specification. The documentation says:因此,也有可能由完成方法的任何其他调用者"执行任务.一个直观的例子是So there’s also the possibility that the task is performed "by any other caller of a completion method". An intuitive example isCompletableFuture<X> f = CompletableFuture.supplyAsync(() -> foo()) .thenApply(f -> f.bar());涉及两个线程.一个调用 supplyAsync 和 thenApply ,另一个调用 foo().如果第二个线程在第一个线程进入 thenApply 的执行之前完成了 foo()的调用,则将来可能已经完成.There are two threads involved. One that invokes supplyAsync and thenApply and the other which will invoke foo(). If the second completes the invocation of foo() before the first thread enters the execution of thenApply, it is possible that the future is already completed.将来不会记得哪个线程完成了它.尽管它可能正在忙于其他事情,甚至从那以后就终止了,但它也不具备告诉该线程执行某项操作的魔术功能.因此很明显,在已经完成的将来调用 thenApply 不能保证使用完成该任务的线程.在大多数情况下,它将在调用 thenApply 的线程中立即执行操作.规范的措辞"完成方法的任何其他调用者"都涵盖了这一点.A future does not remember which thread completed it. Neither does it have some magic ability to tell that thread to perform an action despite it might be busy with something else or even have terminated since then. So it should be obvious that calling thenApply on an already completed future can’t promise to use the thread that completed it. In most cases, it will perform the action immediately in the thread that calls thenApply. This is covered by the specification’s wording "any other caller of a completion method".但这还不是故事的结局.正如此答案所述,当涉及两个以上线程时,该动作也可以由另一个调用不相关线程的线程执行.将来同时完成的方法.这种情况很少发生,但在参考实现中是有可能的,并且在规范中允许.But that’s not the end of the story. As this answer explains, when there are more than two threads involved, the action can also get performed by another thread calling an unrelated completion method on the future at the same time. This may happen rarely, but it’s possible in the reference implementation and permitted by the specification.我们可以将其总结为:没有 Async 的方法对执行动作的线程提供了最少的控制权,甚至可以在调用线程中正确执行它,从而导致同步行为.We can summarize it as: Methods without Async provides the least control over the thread that will perform the action and may even perform it right in the calling thread, leading to synchronous behavior.因此,当执行线程无关紧要并且您不希望后台线程执行(即短暂的无阻塞操作)时,它们是最好的选择.So they are best when the executing thread doesn’t matter and you’re not hoping for background thread execution, i.e. for short, non-blocking operations.这样做的时候future.thenCompose(quote -> CompletableFuture.supplyAsync(() -> Discount.applyDiscount(quote), executor))涉及到三个期货,所以目前尚不清楚,哪个期货是第二". supplyAsync 正在提交操作并返回未来.提交包含在传递给 thenCompose 的函数中,该函数将返回另一个未来.there are three futures involved, so it’s not exactly clear, which future is meant by "second". supplyAsync is submitting an action and returning a future. The submission is contained in a function passed to thenCompose, which will return another future.如果在这里使用了 thenComposeAsync ,则仅要求将 supplyAsync 的执行提交给线程池,而不是直接在完成线程或完成方法的任何其他调用者",例如直接在调用 thenCompose 的线程中.If you used thenComposeAsync here, you only mandated that the execution of supplyAsync has to be submitted to the thread pool, instead of performing it directly in the completing thread or "any other caller of a completion method", e.g. directly in the thread calling thenCompose.关于依赖关系的推理在这里毫无意义." then "始终表示从属关系.如果您在此处使用 thenComposeAsync ,则可以将操作强制提交到线程池中,但是在 future 完成之前仍然不会提交该操作.而且,如果 future 异常完成,提交将根本不会发生.The reasoning about dependencies makes no sense here. "then" always implies a dependency. If you use thenComposeAsync here, you enforced the submission of the action to the thread pool, but this submission still won’t happen before the completion of future. And if future completed exceptionally, the submission won’t happen at all.那么,在这里使用 thenCompose 是否合理?是的,但不是出于报价的原因.如前所述,使用 non-async 方法意味着放弃对执行线程的控制,并且仅应在该线程无关紧要时使用,尤其是对于简短的非阻塞操作.调用 supplyAsync 是一种廉价的操作,它将自己的实际操作提交给线程池,因此可以在任何有空的线程中执行它.So, is using thenCompose reasonable here? Yes it is, but not for the reasons given is the quote. As said, using the non-async method implies giving up control over the executing thread and should only be used when the thread doesn’t matter, most notably for short, non-blocking actions. Calling supplyAsync is a cheap action that will submit the actual action to the thread pool on its own, so it’s ok to perform it in whatever thread is free to do it.但是,这是不必要的并发症.您可以使用However, it’s an unnecessary complication. You can achieve the same usingfuture.thenApplyAsync(quote -> Discount.applyDiscount(quote), executor)将执行完全相同的操作,在 future 完成后将 applyDiscount 提交给 executor ,并产生一个代表结果的新未来.这里不需要结合使用 thenCompose 和 supplyAsync .which will do exactly the same, submit applyDiscount to executor when future has been completed and produce a new future representing the result. Using a combination of thenCompose and supplyAsync is unnecessary here.请注意,这个示例已经在此问题与解答中进行了讨论,该问题也解决了不必要的隔离将来在多个 Stream 操作上进行的操作以及错误的序列图.Note that this very example has been discussed in this Q&A already, which also addresses the unnecessary segregation of the future operations over multiple Stream operations as well as the wrong sequence diagram. 这篇关于作者的理由是正确的,然后使用thenCompose而不是thenComposeAsync的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-11 21:56