2013-06-22 98 views
8

偶爾我們必須在完全關閉整個JVM之前強制性地停止線程作爲盡力而爲的方式。通常引用Thread#stop作爲一個絕對的,即使是無用的和不贊成使用的方式來無條件停止線程。其實並非如此,但是:所有的流氓線程必須做,以保持自身運行的是抓ThreadDeath或超:如何無條件地停止線程

public static void main(String[] args) throws InterruptedException { 
    final Thread t = new Thread() { public void run() { 
    for (;;) 
     try { Thread.sleep(Long.MAX_VALUE); } 
     catch (Throwable t) { 
     System.out.println(t.getClass().getSimpleName() + ". Still going on..."); 
     } 
    }}; 
    t.start(); 
    Thread.sleep(200); 
    t.interrupt(); 
    Thread.sleep(200); 
    t.interrupt(); 
    Thread.sleep(200); 
    t.stop(); 
    Thread.sleep(200); 
    t.stop(); 
} 

這將打印

InterruptedException. Still going on... 
InterruptedException. Still going on... 
ThreadDeath. Still going on... 
ThreadDeath. Still going on... 

還有什麼,我可以做真的,真的停止一個線程而不殺死整個JVM?

+2

我知道它不回答這個問題[但這是一個很好的閱讀主題](http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation。 HTML),它解釋了爲什麼停止首先被棄用。此外,爲什麼你會有一個'胭脂線',可能會首先捕獲TheadDeath和中斷?線程不是爲了那個。他們不提供安全。另一個線程也可以終止JVM本身 - 或者產生其他有問題的線程。 –

+0

這在某種程度上是一個學術問題;我只是想知道每種停止技術究竟做了什麼以及首先有哪些技術。隨着特定需求的出現,這種知識可以拯救你。 –

+0

@BenjaminGruenbaum我建議提交一個簡單的答案「no」:沒有辦法真的,_really_(強行)停止線程而不殺死整個JVM,然後鏈接到那篇文章。 –

回答

5

沒有內置簡單的方法真的停一個線程。

這樣的方法,破壞,was planned but not implemented

已過時。此方法最初設計用於銷燬此線程而不進行任何清理。它保存的任何監視器都將保持鎖定狀態。但是,該方法從未實現過。如果如果要實施,那麼掛起()的方式會很容易出現死鎖。如果目標線程在銷燬時保留了關鍵系統資源的鎖,則線程無法再次訪問此資源。如果另一個線程試圖鎖定這個資源,會導致死鎖。這種僵局通常表現爲「凍結」的過程。

線程不是爲了那個。他們不提供安全。另一個線程也可以終止JVM本身 - 或者產生其他有問題的線程。

有關更多信息,不建議使用see Why are Thread.stop, Thread.suspend and Thread.resume。你可以read why here.

+0

關於不執行'destroy'的說法是很好的;至於其他附帶的評論,它們並不特別突出,因爲它們自從Java 1.4和Java 2以來就已經是常識,因爲一個負責任的程序員可能仍然想要殺死一個特定的目標線程,例如已知的線程不要改變任何共享狀態或保留任何外部資源。 –

+0

引用您的參考文獻:「我們目前並沒有實施['Thread#destroy'],但我們也不會貶低它(將來會阻止它的實現)。雖然它肯定會出現死鎖,但有人認爲有可能是一個程序願意冒死鎖而不是徹底退出的情況。「 –

+0

另一點:通過安裝一個'SecurityManager',可以強制阻止線程終止JVM。 –

0

無法保證該線程可以在Java中停止。最有力的方法是Thread.stop,但這是一個等待發生的事故。替代方法是使用Thread.interrupt並讓線程檢查一個標誌,但這兩個依賴於正確編碼的線程,並且在標誌的情況下,定期檢查它。

個人而言,我會確保我沒有捕捉ThreadDeath。停止是阻止線程的糟糕方法,但至少只要您沒有捕獲ThreadDeath,就應該收到通知。

+0

我從來沒有抓過'ThreadDeath',但是我經常抓住'Throwable',因爲我經常想知道一個例程因爲什麼原因突然完成,並且還保留了一個頂級運行循環。 –

+0

Marko,如果代碼真的捕獲Throwable並繼續前進,從不檢查中斷(或標誌),那麼這就是代碼的錯誤,而不是Java的錯誤。 – user949300

+0

@ user949300一旦你的項目中有不良行爲的外部代碼,發現它不是Java的錯誤並不會讓人感到安慰。 –