2016-08-31 64 views
1

「布爾取消(布爾mayInterruptIfRunning)試圖取消 執行這個任務的。如果任務已經 完成,已取消,或無法取消 一些其他原因這種企圖將會失敗」導致無法取消任務的其他原因是什麼?

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean)

除了上面列出的原因,什麼是它會失敗取消任務其他什麼原因? 此外,如果任務運行下面的代碼可以取消它?

while(true) 
{ 
; 
} 
+0

可能有多種原因,但他們都將屬於類別「下儘管取消請求,任務不會停止「。你的while-true循環將成爲衆多原因之一。 –

+0

@ Erwin,他們有沒有規則\模式? – Jason

+0

也可以取消哪些類型的任務,任何模式? – Jason

回答

2

您發佈的while循環將是不可取消的代碼的一個示例,因爲它對於中斷沒有響應。

阻止偵聽套接字的代碼也可能無法處理中斷。即使代碼超時帶有InterruptedIOException,但如果您在不設置中斷標誌的情況下吞下異常,則代碼可能無法處理中斷。所以TLDR:1)阻止IO的代碼2)不知道中斷如何工作的代碼。或兩者的組合。

0

沒有好的方法可以在Java中實際終止一個線程。基本上可以告訴線程停止,但線程可以不斷等待,永遠不會讀取標誌或類似的問題。這實際上是一個複雜的問題。所以我假設他們只是說「有些問題」。

+0

是否有任何規則\模式可以找到哪些類型的任務可以取消,哪些不能? – Jason

+0

推薦的方法是在線程內定期檢查一個標誌。這真的取決於你如何真正完成一項任務。這顯然只適用於可能永久運行或很長時間的線程。在其他情況下,一旦獲得結果,只需讓線程運行並處理即可。典型情況下,當你的上下文遭到破壞,但你剛剛從一個線程返回。 – breakline

0

每個線程都有一個保存中斷狀態的特殊標誌,它可以通過isInterrupted()方法訪問。當有人中斷某個線程時,該標誌被設置爲true。就這樣。直到由該線程執行的代碼檢查該標誌並且引發InterruptedException或者如果可以退出線程執行,則不會發生真正的中斷。

標準庫中的許多用於阻止當前線程的方法實際上會不時檢查該標誌,並在發現標誌置位時拋出InterruptedException。例如,Thread.sleep()Thread.join(),Object.wait(),Lock.lockInterruptibly()和許多其他。因此,當你的線程週期性地檢查這個標誌或者被一些隱式檢查它的描述方法阻塞時,它是可中斷的。否則,它不是。

因此,具有空循環的線程不能被中斷,因爲它不檢查中斷狀態。但是,增加的中斷狀態檢查將解決這個問題:

while (!Thread.currentThread().isInterrupted()) { } 

調用一個方法響應中斷也將工作:

try { 
    while (true) { 
     Thread.sleep(timeout); 
    } 
} catch(InterruptedException e) { 
    // Do nothing, just let the thread exit 
} 
相關問題