[英]CompletableFuture showing inconsistent threading behavior
CompletableFuture的文檔為異步執行指定了以下行為:
所有沒有顯式Executor參數的異步方法都是使用ForkJoinPool#commonPool()執行的(除非它不支持並行度至少為2,在這種情況下,將創建一個新的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();
但是,重復此測試會產生不一致的結果,因為第二個代碼塊有時會使用公共池。 在這種情況下的預期行為是什么?
看着在OpenJDK執行CompletableFuture后在這里 ,它聞起來像你遇到一種競爭狀態。 假設我們正在執行類似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
,以確保處理程序在某些特定的執行程序池中執行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.