簡體   English   中英

CompletableFuture顯示不一致的線程行為

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM