如果虚拟机被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时运行):

在Java 中捕获Ctrl+C

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

我可以保证在虚拟机退出之前,所有活动线程都将运行完成吗?

与此相关的是,关闭挂钩是否只有在线程全部退出时才会被调用?

当主线程完成或通过Ctrl+C发生键盘中断时,会调用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
}

这保证了所有活动线程都将运行到完成。然而,这不一定是个好主意。引用API文件:

关机挂钩在虚拟机生命周期中的一个微妙时刻运行机器,因此应该进行防御编码。他们应该在特别是,编写时要确保线程安全并避免死锁尽可能[…]关闭挂钩也应该完成它们的快速工作。当程序调用exit时,预期是虚拟机将立即关闭并退出。当虚拟由于用户注销或系统关闭,计算机被终止底层操作系统可能只允许在关闭并退出。因此,尝试是不可取的任何用户交互或在关机挂钩。

相关内容

  • 没有找到相关文章

最新更新