[英]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來模擬更高的負載;-)誰能發現我的錯誤,給我一些建議,以期在哪里看,或建議可以幫助我的工具?
奇怪。 我閱讀代碼的方式與您相同。 我懂了:
FutureTask.get()
調用Sync.get()
。 我假設我們在這里處理FutureTask
。 Sync.get()
調用Sync.innerGet()
Sync.innerGet()
調用Sync.innerGet()
acquireSharedInterruptibly(0)
; 上面有代碼:
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.