如果通过 Control-C 关闭虚拟机,我能否确保计时器启动的线程运行完成?

发布于 2024-12-25 18:49:03 字数 599 浏览 6 评论 0原文

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

 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 时运​​行):

捕获 Ctrl+ Java 中的 C

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

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

与此相关的是,关闭钩子是否仅在线程全部退出时才被调用?

Suppose I make a few calls to the following function:

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

My understanding is that a bunch of threads will be running simultaneously at this point.
That is, each timer instance will be spawning short-lived threads at 1-minute intervals.

Suppose I install a shutdown hook (to run when I press Control-C) per the instructions here:

Catching Ctrl+C in Java

The shutdown hook will cancel all the timers. (Assume that I store the timers in a class-level collection)

Can I guarantee that all the active threads will run to completion before the VM exits?

Related to this, does the shutdown hook only get called when the threads all exit?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

只是一片海 2025-01-01 18:49:03

当主线程完成或通过 Ctrl+C 发生键盘中断时,关闭钩子就会被调用。

如果要保证活动线程将运行完成,则必须在关闭挂钩中显式 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 时,期望是
虚拟机将立即关闭并退出。当虚拟
机器因用户注销或系统关闭而终止
底层操作系统可能只允许固定的时间
关闭并退出。因此不建议尝试
任何用户交互或执行长时间运行的计算
关闭挂钩。

The shutdown hook gets called when either the main thread finishes, or a keyboard interrupt via Ctrl+C occurs.

If you want to guarantee that the active threads will run to completion, you have to explicitly join() them in the shutdown hook. This is slightly tricky, since the threads used by the TimerTasks aren't directly exposed to you, but you could put something like this in your class:

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

And then something like this at the very top of the TimerTask.run() method:

timerThreads.add(Thread.currentThread());

And then something like this in the shutdown hook:

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

This guarantees that all the active threads will run to completion. It is, however, not necessarily a good idea. To quote the API documentation:

Shutdown hooks run at a delicate time in the life cycle of a virtual
machine and should therefore be coded defensively. They should, in
particular, be written to be thread-safe and to avoid deadlocks
insofar as possible. [...] Shutdown hooks should also finish their
work quickly. When a program invokes exit the expectation is that
the virtual machine will promptly shut down and exit. When the virtual
machine is terminated due to user logoff or system shutdown the
underlying operating system may only allow a fixed amount of time in
which to shut down and exit. It is therefore inadvisable to attempt
any user interaction or to perform a long-running computation in a
shutdown hook.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文