对于类Thread
的关闭挂钩是否在调用关闭的线程上运行其可运行代码或者自行运行,存在一些冲突。
addShutdownHook
将Thread
作为参数。这意味着线程将自己启动并运行其run
方法。这也与addShutdownHook
的{{3}}一致:
public void addShutdownHook(Thread hook)
注册新的虚拟机关闭挂钩。 Java虚拟机关闭以响应两种事件:
- 当最后一个非守护程序线程退出或调用退出(等效,System.exit)方法时,程序正常退出,或者
- 虚拟机将终止以响应用户中断,例如键入^ C或系统范围的事件,例如用户注销或系统关闭。
关闭钩子只是一个初始化但未启动的线程。当虚拟机开始其关闭序列时,它将以某种未指定的顺序启动所有已注册的关闭挂钩,并且让它们同时运行。当所有挂钩都完成后,如果启用了finalization-on-exit,它将运行所有未读取的终结器。最后,虚拟机将停止。请注意,守护程序线程将在关闭序列期间继续运行,如果通过调用exit方法启动关闭,则非守护程序线程将继续运行。
(强调我的)
但是,代码为documentation:
/* Run all registered shutdown hooks
*/
private static void runHooks() {
for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {
try {
Runnable hook;
synchronized (lock) {
// acquire the lock to make sure the hook registered during
// shutdown is visible here.
currentRunningHook = i;
hook = hooks[i];
}
if (hook != null) hook.run(); // not Thread.start - Runnable.run (!!)
} catch(Throwable t) {
if (t instanceof ThreadDeath) {
ThreadDeath td = (ThreadDeath)t;
throw td;
}
}
}
}
(!!
评论我的)
请注意,这是来自JDK 6的as follows,这使得问题更加清晰:
/* Run all registered shutdown hooks
*/
private static void runHooks() {
/* We needn't bother acquiring the lock just to read the hooks field,
* since the hooks can't be modified once shutdown is in progress
*/
for (Runnable hook : hooks) {
try {
hook.run();
} catch(Throwable t) {
if (t instanceof ThreadDeath) {
ThreadDeath td = (ThreadDeath)t;
throw td;
}
}
}
}
起初我以为我读错了,并且run
神奇地启动了线程。但事实并非如此。我自己编写了run
代码。该代码不会启动一个线程(在Thread
的情况下,假设run
在线程上运行是自然而正确的。)
这里有些东西真的错了。它是Javadoc和addShutdownHook
方法的签名,根据代码应该不是一个线程,而是一个可运行的?是实施吗?或者更可能是罪魁祸首 - 我;如果是的话,怎么样?
答案 0 :(得分:4)
您感到困惑Shutdown.runHooks()
和ApplicationShutdownHooks.runHooks()
。您在Runtime
注册的关闭挂钩已在ApplicationShutdownHooks
注册,Runnable
本身将Shutdown
注册为static {
try {
Shutdown.add(1 /* shutdown hook invocation order */,
false /* not registered if shutdown in progress */,
new Runnable() {
public void run() {
runHooks(); // (!!) your hooks
}
}
);
hooks = new IdentityHashMap<>();
} catch (IllegalStateException e) {
// application shutdown hooks cannot be added if
// shutdown is in progress.
hooks = null;
}
}
挂钩
static void runHooks() { // In ApplicationShutdownHooks
Collection<Thread> threads;
synchronized(ApplicationShutdownHooks.class) {
threads = hooks.keySet();
hooks = null;
}
for (Thread hook : threads) { // (!!) your hooks
hook.start();
}
for (Thread hook : threads) {
try {
hook.join();
} catch (InterruptedException x) { }
}
}
关闭挂钩同时运行
Runtime#addShutdownHook(Thread)
供参考,public void addShutdownHook(Thread hook) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("shutdownHooks"));
}
ApplicationShutdownHooks.add(hook);
}
的{{1}}