2010-08-17 58 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