簡體   English   中英

在調用Future.get()之前中斷線程

[英]Interrupting a thread prior to calling Future.get()

我正在嘗試編寫一個集成測試,該測試會導致從生產代碼中引發InterruptedException

@Test
public void test() {
    productionObject = new ProductionObject(
            com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor());
    Thread.currentThread().interrupt();
    assertThat(productionObject.execute(), equalTo(defaultResponse));
}

內部productionObject的實現:

try {
    for (Future<T> future : executorService.invokeAll(tasks))) {
        results.add(future.get());
    }
    return results;
} catch (InterruptedException e) {
    Thread.currentThread().interrupt(); // preserve interrupt flag
    return defaultResponse;
}

AbstractQueuedSynchronizer.acquireSharedInterruptibly()內部,我看到:

  if (Thread.interrupted())
        throw new InterruptedException();

因此,我希望該測試能夠始終如一地通過。

我已經在構建服務器中看到了此失敗(返回results而不是defaultResponse )。 我一直無法在本地重現故障,無法在一段時間(true)的循環中運行測試,並且無法通過運行帶有軟件渲染功能的glxgears來模擬更高的負載;-)誰能發現我的錯誤,給我一些建議,以期在哪里看,或建議可以幫助我的工具?

奇怪。 我閱讀代碼的方式與您相同。 我懂了:

  1. FutureTask.get()調用Sync.get() 我假設我們在這里處理FutureTask
  2. Sync.get()調用Sync.innerGet()
  3. Sync.innerGet()調用Sync.innerGet() acquireSharedInterruptibly(0)
  4. 上面有代碼:

     if (Thread.interrupted()) throw new InterruptedException(); 

我認為這將永遠拋出。 也許存在某種競爭狀況,所以線程尚不知道它已被中斷? 中斷線程后,您是否嘗試過睡眠100毫秒?

我只是在多CPU Mac上運行了以下測試,但它從未失敗過,因此它看起來並不像競爭條件-至少對於我的體系結構和JRE 1.6.0_41版​​本而言。

for (long i = 0; i < 10000000; i++) {
    Thread.currentThread().interrupt();
    assertTrue(Thread.interrupted());
}

在這種情況下使用sameThreadExecutor()實際上可能sameThreadExecutor() ,因為中斷可能比其中一項任務發生。 否則,代碼看起來很好。 嘗試使用實際的其他線程作為開始,讓其中一項任務等待足夠長的時間來進行中斷。

我通過從Callable而不是從測試方法本身中斷線程來“修復”此問題。 這使得中斷發生得更接近於調用acquireSharedInterruptibly()

我只能想象在代碼路徑上的某個地方有時會清除中斷標志(也許是通過JUnit或Maven surefire,它們並行執行測試方法)。 我可能只是降低了競爭狀況的可能性,而不是解決它:-/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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