办公自动化(OA)是面向组织的日常运作和管理,员工及管理者使用频率最高的应用系统,既可以用来搭建企业网站,也可聚合在政府网站中,应用广泛。
文件:590m.com/f/25127180-498614174-c340c8(访问密码:551685)
以下内容无关:
-------------------------------------------分割线---------------------------------------------
如果想在 Java 进程退出时,包括正常和异常退出,做一些额外处理工作,例如资源清理,对象销毁,内存数据持久化到磁盘,等待线程池处理完所有任务等等。特别是进程异常挂掉的情况,如果一些重要状态没及时保留下来,或线程池的任务没被处理完,有可能会造成严重问题。那该怎么办呢?
Java 中的 Shutdown Hook 提供了比较好的方案。我们可以通过 Java.Runtime.addShutdownHook(Thread hook) 方法向 JVM 注册关闭钩子,在 JVM 退出之前会自动调用执行钩子方法,做一些结尾操作,从而让进程平滑优雅的退出,保证了业务的完整性。
Shutdown Hook 介绍
其实,shutdown hook 就是一个简单的已初始化但是未启动的线程。当虚拟机开始关闭时,它将会调用所有已注册的钩子,这些钩子执行是并发的,执行顺序是不确定的。
在虚拟机关闭的过程中,还可以继续注册新的钩子,或者撤销已经注册过的钩子。不过有可能会抛出 IllegalStateException。注册和注销钩子的方法定义如下:
public void addShutdownHook(Thread hook) {
// 省略
}
public void removeShutdownHook(Thread hook) {
// 省略
}
关闭钩子被调用场景
关闭钩子可以在以下几种场景被调用:
程序正常退出
程序调用 System.exit() 退出
终端使用 Ctrl+C 中断程序
程序抛出异常导致程序退出,例如 OOM,数组越界等异常
系统事件,例如用户注销或关闭系统
使用 Kill pid 命令杀掉进程,注意使用 kill -9 pid 强制杀掉不会触发执行钩子
验证程序正常退出情况
package com.chenpi;
public class ShutdownHookDemo {
static {Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("执行钩子方法...")));
}public static void main(String[] args) throws InterruptedException {System.out.println("程序开始启动...");Thread.sleep(2000);System.out.println("程序即将退出...");
}
}
运行结果
程序开始启动…
程序即将退出…
执行钩子方法…
Process finished with exit code 0
验证程序调用 System.exit() 退出情况
package com.chenpi;
public class ShutdownHookDemo {
static {Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("执行钩子方法...")));
}public static void main(String[] args) throws InterruptedException {System.out.println("程序开始启动...");Thread.sleep(2000);System.exit(-1);System.out.println("程序即将退出...");
}
}
运行结果
程序开始启动…
执行钩子方法…
Process finished with exit code -1
验证终端使用 Ctrl+C 中断程序,在命令行窗口中运行程序,然后使用 Ctrl+C 中断
package com.chenpi;
public class ShutdownHookDemo {
static {Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("执行钩子方法...")));
}public static void main(String[] args) throws InterruptedException {System.out.println("程序开始启动...");Thread.sleep(2000);System.out.println("程序即将退出...");
}
}
运行结果
D:\IdeaProjects\java-demo\java ShutdownHookDemo
程序开始启动…
执行钩子方法…
演示抛出异常导致程序异常退出
package com.chenpi;
public class ShutdownHookDemo {
static {Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("执行钩子方法...")));
}public static void main(String[] args) {System.out.println("程序开始启动...");int a = 0;System.out.println(10 / a);System.out.println("程序即将退出...");
}
}
运行结果
程序开始启动…
执行钩子方法…
Exception in thread “main” java.lang.ArithmeticException: / by zero
at com.chenpi.ShutdownHookDemo.main(ShutdownHookDemo.java:12)
Process finished with exit code 1
至于系统被关闭,或者使用 Kill pid 命令杀掉进程就不演示了,感兴趣的可以自行验证。
注意事项
可以向虚拟机注册多个关闭钩子,但是注意这些钩子执行是并发的,执行顺序是不确定的。