如何解决如果链中的第一个方法是异步的,那么一系列方法调用 (CompletableFuture API) 是否会异步执行?
我正在学习 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)
(有一个 Executor)
last 表示此操作将在您传递给它的 Executor
中执行,这是最明显的一个。
second 表示在 ForkJoinPool
中执行操作。
第一个要有趣得多。该文档听起来很简单,通过:
为非异步方法的依赖完成提供的操作可以由完成当前 CompletableFuture 的线程执行,或者由完成的任何其他调用者执行方法
你需要开始把它分成更小的部分。您需要了解的是,有些线程完成某个CompletableFuture
,有些线程对它执行某些操作,有些线程链 某些依赖动作。可能,这些都是不同的线程。这就是一切的开始:
-
如果依赖动作已经被链接,调用
complete
的线程将成为执行该动作的线程。 -
如果未来已经完成,那么链接动作的线程将执行它。
由于上述步骤没有线性操作,因此实际上无法确定您的 thenApply
将在哪个线程中执行,至少 100% 确定。该操作可以在以下任何一个中执行:
- 调用
complete/completeExceptionally
的线程 - 链接
thenApply
的线程 - 调用
join/get
的线程
以上任何一种都是可能的。如果你真的想要,我做了一个相当有趣的 test here,证明了上面的一些事情。
我不是要选择另一个答案,但他提出了一个相当有趣的观点,我在乞求中也很困惑:
在您的示例中:在 .thenComposeAsync
之后,所有以下链式期货也将由执行者完成。
我们可以很容易地证明这是不正确的:
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
,而不是池中的线程。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。