Java TimerTask一直在运行

Java TimerTask一直在运行,java,multithreading,task,schedule,Java,Multithreading,Task,Schedule,我有一个关于Java中计时器类行为的问题。 代码如下: 如果你运行这个程序,它会打印“是的!”而不会做任何其他事情(程序不会结束) Java文档说明: 在对计时器对象的最后一个实时引用消失并且所有未完成的任务都已完成执行后,计时器的任务执行线程将正常终止(并成为垃圾收集的对象) 正如我看到的,在'foo()'函数结束后,对计时器对象的“最后一次实时引用”就消失了。计划的唯一任务是执行的“Yes!”任务,所以我猜在进程打印“Yes!”之后,计时器对象应该结束,进程应该终止 这里发生了什么?Java

我有一个关于Java中计时器类行为的问题。 代码如下:

如果你运行这个程序,它会打印“是的!”而不会做任何其他事情(程序不会结束)

Java文档说明: 在对计时器对象的最后一个实时引用消失并且所有未完成的任务都已完成执行后,计时器的任务执行线程将正常终止(并成为垃圾收集的对象)

正如我看到的,在'foo()'函数结束后,对计时器对象的“最后一次实时引用”就消失了。计划的唯一任务是执行的“Yes!”任务,所以我猜在进程打印“Yes!”之后,计时器对象应该结束,进程应该终止


这里发生了什么?

Java没有退出,因为运行计时器的线程仍在运行。在Java退出之前,必须将该线程标记为守护进程线程。您可能无法访问线程本身,因此除非计时器有一个标记它的方法,否则您将很难做到这一点。您需要在finally子句中手动停止它

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

我相信下面的代码应该可以做到这一点

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 {
  SysPrint(Timer timer) {
    this.timer = timer;
  }

  public void run() {
    System.out.println("Yes!");
    timer.cancel();
  }

  private Timer timer;
}

创建计时器对象时。将创建一个TimerRead。它是运行任务的内部线程。您可以查看TimerThread的run()方法。你可以看到它有一个while循环

 private void mainLoop() {
    while (true) {....
TimerThread未设置为守护进程,因此主方法完全执行,jvm不存在


这就是为什么你的程序总是在运行,而且不会停止。

我想这不是我问题的答案。甚至连“是”字都没印出来。它调度它,然后取消线程。@makakko:不要调用
main()
中的
cancel()
方法,而是从
SysPrint.run()
方法中调用
TimerTask.cancel()
方法。如javavdoc中所述,运行任务后需要调用cancel:“在对计时器对象的最后一次实时引用消失并且所有未完成的任务都已完成执行后,计时器的任务执行线程将正常终止(并成为垃圾收集的对象)。但是,这可能需要任意长的时间。默认情况下,任务执行线程不作为守护进程线程运行,因此它能够防止应用程序终止。如果调用方希望快速终止计时器的任务执行线程,则调用方应调用计时器的cancel方法。“感谢所有人的回答。这种行为非常奇怪。请查看ScheduledExecutorService
 private void mainLoop() {
    while (true) {....