CompletableFuture的文档为异步执行指定了以下行为:
使用ForkJoinPool#commonPool()执行没有显式Executor参数的所有 async 方法(除非它不支持至少两个并行级别,在这种情况下,创建一个新的Thread运行每个任务)。为了简化监视,调试和跟踪,所有生成的异步任务都是标记接口AsynchronousCompletionTask的实例。
然而,同步(或至少非异步)方法的行为仍不清楚。在大多数情况下,代码使用原始线程执行,如下所示:
Thread thread = Thread.currentThread();
CompletableFuture.runAsync(() -> {
// Should run on the common pool - working as expected
assert thread != Thread.currentThread();
}).thenRun(() -> {
// Returns to running on the thread that launched.. sometimes?
assert thread == Thread.currentThread();
}).join();
但是,重复此测试会产生不一致的结果,因为第二个代码块有时会使用公共池。在这种情况下的预期行为是什么?
答案 0 :(得分:0)
在查看CompletableFuture here的OpenJDK实现后,它闻起来就像是遇到了一种竞争条件。假设我们正在按照runAsync(a).thenRun(b)
的方式做一些事情。如果a
在当前线程上调用thenRun(b)
之前在公共池线程上完成执行,那么b
会在thenRun(b)
最终被调用后立即在当前线程上运行。另一方面,如果在thenRun(b)
完成另一个线程之前调用a
,那么b
最后a
与a
在同一个线程上运行class CompletableFuture:
function runAsync(a):
function c():
run a
for each b in the handler stack:
run b
run c on a different thread
return future representing c
function thenRun(b):
if c is done:
run b
else:
put b in c's handler stack
饰面。
有点像这样:
b
显然,如果在c
完成之前调用thenRun
,则a
会在b
的主题中运行。否则,CompletableFuture#thenRunAsync
将在当前线程中运行。
如果你想在哪个线程运行的方面有更一致的行为,你应该尝试使用ps aux | grep mongo
,这可以保证处理程序在某个特定的执行器池中执行。