![](/img/trans.png)
[英]What happens to terminated tasks in a ScheduledExecutorService?
[英]What happens when the JVM is terminated?
使用System.exit(0)
或^C
或类似的任何东西终止JVM时会发生什么? 我读过“过程刚被吹走”和“每一个线程都被停止”之类的东西,但我想知道究竟发生了什么。 我已经知道有一些shutdownHook
仍然会被执行,但是在调用shutdownHooks之前会发生什么,并且在所有这些线程完成之后会发生什么?
我想正确地实现这样的shutdownHook
,并且这样做我需要对可能仍然执行的内容和不执行的内容做出正确的假设。
一些代码:
class SomeObject {
private boolean stopped;
SomeObject() {
stopped = false;
Thread hook = new Thread() {
@Override
public void run() {
stopped = true;
}
};
hook.setPriority(Thread.MAX_PRIORITY);
Runtime.getRuntime().addShutdownHook(hook);
}
boolean map(Iterator<Object> it) {
while(it.hasNext() && !stopped) {
writeToOtherObject(it.next());
it.remove();
}
//have calculations finished?
return !it.hasNext();
}
}
map
函数计算在其他对象中收集的结果。 在破坏所有内容之前,应将此对象存储在某个文件中(通过普通优先级shutdownHook
也是如此)。 shutdownHook
在这里有意义吗? 据我所知,所有线程首先被销毁,然后才运行shutdownHook
(同时,但我假设首先运行高优先级线程......)然后最终确定对象。 这使得上面的代码相当无用,因为这个shutdownHook
的目的是确保在关闭已经开始时没有启动新的循环。 我的理解是正确和完整的吗?
让我们从可以启动关闭序列的不同方式开始:
System.exit()
或Runtime.exit()
。 调用System.exit(int)
,它调用Runtime.exit()
。 它检查安全管理器是否允许以给定状态退出,如果是,则调用Shutdown.exit()
。
如果您中断了JVM或系统向其发送了TERM信号,则默认情况下,直接调用Shutdown.exit()
而不检查安全管理器。
Shutdown
类是java.lang
的内部包私有类。 除其他外,它有exit()
和halt()
方法。 它的exit()
方法做了一些事情来阻止钩子被执行两次,依此类推,但基本上,它的作用是什么
join
。 其他系统挂钩可以在应用程序挂钩之前或之后运行。 runFinalizersOnExit
。 现在,与您的假设相反,在第3阶段,所有线程都停止了。 halt
方法是本机的,我没有尝试读取本机代码,但是直到它被调用的那一刻,运行的唯一代码是纯Java,并且没有任何东西可以阻止其中的任何地方的线程。 Runtime.addShutdownHook
的文档实际上说:
关闭钩子只是一个初始化但未启动的线程。 当虚拟机开始其关闭序列时,它将以某种未指定的顺序启动所有已注册的关闭挂钩,并让它们同时运行。 当所有挂钩都完成后,如果启用了finalization-on-exit,它将运行所有未读取的终结器。 最后,虚拟机将停止。 请注意,守护程序线程将在关闭序列期间继续运行,如果通过调用exit方法启动关闭,则非守护程序线程也将继续运行。
(强调我的)
所以你看,它确实是关闭钩子的工作的一部分,告诉线程他们应该离开他们的循环并清理。
另一个误解是关于给线程一个高优先级。 高优先级并不意味着线程将在所有其他挂钩之前首先运行。 它只是意味着每当操作系统必须决定哪个线程处于“准备运行”状态以给CPU运行时,高优先级线程将具有更高的“获胜”概率 - 取决于关于操作系统的调度算法。 简而言之,它可能会获得更多的CPU访问权限,但它不会 - 特别是如果你有多个CPU核心 - 必须在其他线程之前启动或在它们之前完成。
最后一件事 - 如果你想使用一个标志告诉一个线程停止工作,那个标志应该是volatile
。
看看DZone的这篇文章 。 它详细介绍了JVM及其终止,重点介绍了ShutdownHook
的使用。
从较高层面来看,它涵盖的一些重要假设包括:
- 在某些情况下可能无法执行关机挂钩!
- 一旦启动,可以在完成之前强制停止关机挂钩。
- 您可以拥有多个Shutdown Hook,但不保证其执行顺序。
- 您无法在Shutdown Hooks中注册/取消注册Shutdown Hooks
- 一旦关闭序列启动,它只能由Runtime.halt()停止。
- 使用关闭挂钩需要安全权限。
- Shutdown Hooks抛出的异常与任何其他代码段抛出的异常一样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.