我正在研究 CompletableFuture API,有一个例子:
CompletableFuture.completedFuture(url)
.thenComposeAsync(this::readPage, executor)
.thenApply(this::getImageURLs)
.thenApply(this::saveFoundImages)
.....
我有一个问题:如果我调用 thenComposeAsync(...)
方法作为第一个方法,链中的其他方法是否会在 executor
中执行?我通过参数传递了哪个,或者我应该使用 async 调用其他方法以在特定执行器中异步执行?
最佳答案
好的,所以CompletableFuture
中有3种方法.例如:
thenApply()
thenApplyAsync(Function)
(没有执行者)thenApplyAsync(Function, Executor)
(与执行人)最后一个表示这个 Action 会在
Executor
中执行。你传递给它,这是最明显的一个。第二个表示 Action 在
ForkJoinPool
中执行.第一个更有趣。该文档通过以下方式使它听起来很容易:
Actions supplied for dependent completions of non-async methods may be performed by the thread that completes the current CompletableFuture, or by any other caller of a completion method
你需要开始把它分成更小的部分。你需要了解的是有线程完成某个
CompletableFuture
,有一些线程对其执行一些操作,也有一些线程链接某些相关的操作。潜在地,这些都是不同的线程。这就是一切的开始:complete
的线程将成为执行此操作的线程。由于上述步骤没有线性 Action ,因此实际上不可能确定您的
thenApply
在哪个线程中。将执行,至少有 100% 的确定性。该 Action 可以在以下任何一个中执行:complete/completeExceptionally
的线程thenApply
的线程join/get
的线程以上任何一种情况都有可能。如果你真的想要我做了一个相当有趣的test here ,证明了上面的一些事情。
我不想选择其他答案,但他提出了一个相当有趣的观点,我在乞讨时也很困惑:
In your example: After
.thenComposeAsync
also all the following chained futures will get completed by executor.
我们可以很容易地证明这是不正确的:
CompletableFuture<String> future1 = CompletableFuture.completedFuture("a");
CompletableFuture<String> future2 = future1.thenApplyAsync(x -> "b" + x, Executors.newCachedThreadPool());
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
CompletableFuture<String> future3 = future2.thenApply(x -> {
System.out.println(Thread.currentThread().getName());
return x + "c";
});
future3.join();
如果你运行它,你会看到main
实际执行 thenApply
,而不是池中的线程。
关于java - 如果链中的第一个方法是异步的,则方法调用链(CompletableFuture API)是否会异步执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65685715/