CompletableFuture 显示不一致的线程行为
CompletableFuture showing inconsistent threading behavior
CompletableFuture 的文档指定了异步执行的以下行为:
All async methods without an explicit Executor argument are performed using the ForkJoinPool#commonPool() (unless it does not support a parallelism level of at least two, in which case, a new Thread is created to run each task). To simplify monitoring, debugging, and tracking, all generated asynchronous tasks are instances of the marker interface 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();
但是,重复此测试会产生不一致的结果,因为第二个代码块有时会改用公共池。这种情况下的预期行为是什么?
在查看了 CompletableFuture here 的 OpenJDK 实现后,您似乎遇到了某种竞争条件。假设我们正在按照 runAsync(a).thenRun(b)
的方式做某事。如果 a
在 thenRun(b)
在当前线程上被调用之前完成公共池线程上的执行,那么 b
是 运行 立即在当前线程上一次 thenRun(b)
finally被调用。另一方面,如果 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
显然,如果在 a
完成之前调用 thenRun
,则 b
在 c
的线程中是 运行。否则,b
在当前线程中是运行。
如果您希望在哪个线程 运行 和什么方面有更一致的行为,您应该尝试使用 CompletableFuture#thenRunAsync
,它保证处理程序在某个特定的执行程序池中执行。
CompletableFuture 的文档指定了异步执行的以下行为:
All async methods without an explicit Executor argument are performed using the ForkJoinPool#commonPool() (unless it does not support a parallelism level of at least two, in which case, a new Thread is created to run each task). To simplify monitoring, debugging, and tracking, all generated asynchronous tasks are instances of the marker interface 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();
但是,重复此测试会产生不一致的结果,因为第二个代码块有时会改用公共池。这种情况下的预期行为是什么?
在查看了 CompletableFuture here 的 OpenJDK 实现后,您似乎遇到了某种竞争条件。假设我们正在按照 runAsync(a).thenRun(b)
的方式做某事。如果 a
在 thenRun(b)
在当前线程上被调用之前完成公共池线程上的执行,那么 b
是 运行 立即在当前线程上一次 thenRun(b)
finally被调用。另一方面,如果 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
显然,如果在 a
完成之前调用 thenRun
,则 b
在 c
的线程中是 运行。否则,b
在当前线程中是运行。
如果您希望在哪个线程 运行 和什么方面有更一致的行为,您应该尝试使用 CompletableFuture#thenRunAsync
,它保证处理程序在某个特定的执行程序池中执行。