2010-08-17 105 views
2

我對Java中Timer類的行爲有疑問。 這是代碼:「是的!」 http://pastebin.com/mqcL9b1nTimerTask保持運行

public class Main { 

    public static void main(String[] args) { 
     Main m = new Main(); 
     m.foo(); 
     m = null; 
    } 

    public void foo() 
    { 
     Timer t = new Timer(); 
     t.schedule(new SysPrint(), 200); 
    } 

} 

class SysPrint extends TimerTask 
{ 
    public void run() 
    { 
     System.out.println("Yes!"); 
    } 
} 

什麼情況是,如果你運行該程序,它會打印它不會做任何事情(程序不會結束)。

Java文檔說: 的最後一次現場引用一個Timer對象消失,所有未完成的任務已完成執行後,計時器的任務執行線程終止優雅(併成爲受垃圾收集)。

正如我所看到的那樣,在'foo()'函數結束後,Timer對象的「上次活動引用」消失了。唯一的任務是「是的!」被執行的任務,所以我想在過程打印「是!」後,Timer對象應該結束並且進程應該終止。

這裏發生了什麼事?

+0

看看ScheduledExecutorService – 2010-08-17 19:45:21

回答

2

Java不會退出,因爲您的運行Timer的線程仍然在踢。 Java必須在Java退出之前將該線程標記爲守護程序線程。你可能無法訪問線程本身,除非Timer有一個方法來標記它,所以你將很難做到這一點。您需要在finally子句中手動停止它。

try { 
    timer = new Timer(); 
    timer.schedule(new SysPrint(), 200); 
} finally { 
    timer.cancel(); 
} 
+0

我認爲這不是我的問題的答案。那甚至從不運行「是!」打印也許。它安排它,然後取消線程。 – makakko 2010-08-17 03:18:53

+0

@makakko:不要在'main()'中調用'cancel()'方法,而是從'SysPrint.run()'方法中調用'TimerTask.cancel()'方法。 – 2010-08-17 04:33:09

+0

如javavdoc中所述,在運行任務後需要調用cancel: 「在對Timer對象的最後一次活動引用消失並且所有未完成任務已完成執行後,計時器的任務執行線程將優雅地終止(並受垃圾回收),然而,這可能需要很長時間才能發生,默認情況下,任務執行線程不會作爲守護進程線程運行,所以它能夠阻止應用程序終止如果調用者想要終止一個定時器的任務執行線程迅速,調用者應該調用定時器的取消方法。「 – crafty 2010-08-17 04:41:18