java面试题网站:www.javaoffers.com
参考书籍: java并发编程实战.
jvm在正常关闭时会调用以注册的关闭钩子(ShutDown Hook), 通过 Runtime.getRuntime().addShutdownHook(Thread) 注册关闭钩子, jvm不保证关闭钩子的执行顺序. 在jvm关闭时,如果有线程(守护线程和非守护线程)仍然在运行, 那么这些线程将与关闭钩子线程一起并发执行, 当所有关闭钩子正常执行结束时,jvm会运行终结器,然后再停止. 当jvm最终结束时(会有一定的等待时间),所有的线程被强行结束. 如果关闭钩子或终结器没有执行完成 那么关闭钩子或终结器将会挂起并且jvm将会强制性关闭,但是不会允许 '关闭钩子’线程有可能也会将其强制杀死. 关闭钩子会影响jvm的关闭.所以关闭钩子的业务逻辑通常是非常简单的,不会造成死锁的. 比如 clean 临时日志, 或 项目的运行时的临时数据等.
一个小案例:
/**
* 关闭钩子
*/
public class ShutdownHook {
/**
* jvm关闭时调起关闭钩子
* @throws InterruptedException
*/
@Test
public void testShutdownHook() throws InterruptedException {
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
LOGUtils.printLog("jvm关闭时调起关闭钩子");
try {
int i = 0;
for(;;){
i++;
if(i>5){
break;
}
Thread.sleep(1000);
LOGUtils.printLog("jvm的关闭钩子 模拟业务执行 "+i+"秒");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}));
Thread.sleep(3000);
LOGUtils.printLog("main 线程退出 jvm 退出");
}
}
打印日志:
2020-06-21 15:07:20 []-[INFO] main 线程退出 jvm 退出
2020-06-21 15:07:20 []-[INFO] jvm关闭时调起关闭钩子
2020-06-21 15:07:21 []-[INFO] jvm的关闭钩子 模拟业务执行 1秒
2020-06-21 15:07:22 []-[INFO] jvm的关闭钩子 模拟业务执行 2秒
2020-06-21 15:07:23 []-[INFO] jvm的关闭钩子 模拟业务执行 3秒
2020-06-21 15:07:24 []-[INFO] jvm的关闭钩子 模拟业务执行 4秒
2020-06-21 15:07:25 []-[INFO] jvm的关闭钩子 模拟业务执行 5秒
2020-06-21 15:07:25 []-[INFO] jvm的关闭钩子执行完毕!!!