2010-12-15 61 views
5
package util.concurrent; 

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.TimeUnit; 

public class ShutdownDemo { 
public static void main(String[] args) throws InterruptedException{ 
    ExecutorService executor = Executors.newSingleThreadExecutor(); 

    executor.execute(new Runnable(){ 

    @Override 
    public void run() { 
    while(true){ 
    System.out.println("-- test --"); 
    } 
    } 

    }); 

    TimeUnit.SECONDS.sleep(3); 

    executor.shutdownNow(); 
} 
} 

我已經調用了shutdownNow方法,爲什麼控制檯繼續打印「 - test - 」??爲什麼ExecutorService.shutdownNow方法不能停止線程

回答

1

JavaDocs,ExecutorService#shutdownNow方法不保證實際上停止正在執行的作業。你最好改變一些狀態變量,長時間運行的作業會定期檢查並檢測變化,退出運行循環。

+1

這被誇大了。您的狀態變量與已由Thread.interrupted提供的狀態變量沒有區別。它的行爲方式完全相同。雖然你可以編寫代碼來確保shutdownNow()不會完成 - 這是作者的錯誤 - 如果你遵循規則,我說它最終會關閉。網絡調用最終會超時,但在那段時間沒有過期的情況下,線程將不得不等待,直到超時異常被拋出。對於共享狀態變量也是如此。 – chubbsondubs 2013-08-24 21:13:03

10

退房Thread.stop()以在Javadoc爲充分理由:

http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#stop()

從本質上講,你的線程必須停止在它自己的才能爲你的程序的安全。只是停止一個線程可能會使程序處於不可預知的狀態,線程擁有的鎖不會被釋放,並且資源也不會返回給操作系統。最終會讓程序處於死鎖狀態,無法釋放的內存泄漏,並可能影響操作系統的穩定性。如果你使用C或任何其他語言,這確實沒有什麼不同,因爲停止本機線程有這些問題。記住線程不是它們共享內存並與其他線程共同處理的進程,因此它們必須表現和配合。

Java在中斷線程上起作用,而不是殺死線程,因此線程在寫入時必須符合此模型。因此,你的程序中的(真)是壞習慣。相反,您需要查看您的線程是否已被中斷,並自行關閉。使用Thread.sleep並正確處理InterruptedException。或者在while循環中檢查Thread.isInterrupted()。

+0

但是這是'Runnable'的一個實例 - 我們可以從哪裏得到'Thread.isInterrupted()'?另外,如果'shutdownNow()'試圖在它不休眠時中斷我們的線程,它將只設置中斷標誌,並且當我們再次sleep()時不會產生'InterruptedException'(如果我正確理解了這些文檔)。 – drevicko 2012-10-23 06:24:46

+1

通過使用Thread.currentThread()。isInterrupted(),您始終可以獲得執行該代碼的任何部分的線程。記住一旦線程中斷,任何sleep()或wait()都會產生InterruptedException。 – chubbsondubs 2012-10-23 15:28:00

+0

很酷,謝謝(爲了確保我已經正確理解了,如果我們的線程'interrupt()'被調用並且我們不是sleep(),那麼稍後我們會sleep()一下, InterruptedException是立即生成的嗎?大概這是Java規範的一部分,應該在所有虛擬機的/標準庫中實現? – drevicko 2012-10-23 22:21:50