【问题标题】:TimerTask keeps runningTimerTask 继续运行
【发布时间】:2010-08-17 03:04:01
【问题描述】:

我对 Java 中 Timer 类的行为有疑问。 这是代码:http://pastebin.com/mqcL9b1n

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!");
    }
}

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

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

当我看到这件事时,对 Timer 对象的“最后一个实时引用”在 'foo()' 函数结束后消失了。唯一安排的任务是“是!”执行的任务,所以我猜在进程打印“是!”之后,Timer 对象应该结束并且进程应该终止。

这里发生了什么?

【问题讨论】:

  • 看看 ScheduledExecutorService

标签: java multithreading task schedule


【解决方案1】:

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

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

【讨论】:

  • 我认为这不是我的问题的答案。那甚至从不运行“是!”打印也许。它调度它,然后取消线程。
  • @makakko:不要在main() 中调用cancel() 方法,而是在SysPrint.run() 方法中调用TimerTask.cancel() 方法。
  • 如 javavdoc 中所述,您需要在运行任务后调用取消:“在对 Timer 对象的最后一个实时引用消失并且所有未完成的任务都已完成执行后,计时器的任务执行线程终止优雅地(并成为垃圾回收的对象)。但是,这可能需要任意长的时间。默认情况下,任务执行线程不作为守护线程运行,因此它能够防止应用程序终止。如果调用者想要要快速终止定时器的任务执行线程,调用者应该调用定时器的取消方法。"
  • 感谢大家的回答。这种行为很奇怪。
【解决方案2】:

我相信下面的代码应该可以解决问题。

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;
}

【讨论】:

    【解决方案3】:

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

     private void mainLoop() {
        while (true) {....
    

    TimerThread 没有设置为守护进程,所以 main 方法执行完毕,jvm 不存在。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-04
      • 2017-04-29
      • 1970-01-01
      • 2016-12-16
      • 2015-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多