CompletableFuture显示不一致的线程行为

时间:2017-11-25 02:40:08

标签: java multithreading completable-future

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();

但是,重复此测试会产生不一致的结果,因为第二个代码块有时会使用公共池。在这种情况下的预期行为是什么?

1 个答案:

答案 0 :(得分:0)

在查看CompletableFuture here的OpenJDK实现后,它闻起来就像是遇到了一种竞争条件。假设我们正在按照runAsync(a).thenRun(b)的方式做一些事情。如果a在当前线程上调用thenRun(b)之前在公共池线程上完成执行,那么b会在thenRun(b)最终被调用后立即在当前线程上运行。另一方面,如果在thenRun(b)完成另一个线程之前调用a,那么b最后aa在同一个线程上运行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 ,这可以保证处理程序在某个特定的执行器池中执行。