如果VM被Control-C关闭,我可以确保我的定时器启动线程运行完成吗?

时间:2012-01-09 06:37:18

标签: java command-line java-6 control-c

假设我对以下函数进行了几次调用:

 public void StartTimedRuns(){
    Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask(){
        public void run(){
            //do something that takes less than a minute
        }
    }, 0, 60*1000);
 }

我的理解是此时会有一堆线程同时运行。 也就是说,每个计时器实例将以1分钟的间隔生成短期线程。

假设按照此处的说明安装了一个关闭钩子(按下Control-C时运行):

Catching Ctrl+C in Java

关闭挂钩将取消所有计时器。 (假设我将计时器存储在类级别集合中)

我可以保证在VM退出之前所有活动线程都会运行完毕吗?

与此相关,只有在线程全部退出时才会调用shutdown hook吗?

1 个答案:

答案 0 :(得分:5)

当主线程完成或通过Ctrl + C发生键盘中断时,将调用shutdown hook。

如果要保证活动线程将运行完成,则必须在shutdown hook中显式join()它们。这有点棘手,因为TimerTask使用的线程没有直接暴露给你,但是你可以在你的类中加入类似的东西:

private static List<Thread> timerThreads = new LinkedList<Thread>();

然后在TimerTask.run()方法的最顶端出现类似的内容:

timerThreads.add(Thread.currentThread());

然后在关闭钩子中这样的事情:

try {
    for (Thread t : timerThreads) {
        t.join();
    }
} catch (InterruptedException e) {
    // handle it somehow
}

这可以保证所有活动线程都将运行完成。然而,这不一定是个好主意。引用the API documentation

  

关闭挂钩在虚拟生命周期的微妙时间运行   机器,因此应该进行防御性编码。他们应该在   特别是,写成线程安全并避免死锁   尽可能的。 [...] 关机挂钩也应该完成他们的   工作很快。当程序调用{​​{1}}时,期望就是那样   虚拟机将立即关闭并退出。当虚拟   机器因用户注销或系统关闭而终止   底层操作系统可能只允许一段固定的时间   哪个关闭并退出。因此,不宜尝试   任何用户交互或执行长时间运行的计算   关机钩。