Java关闭钩子的应用 - Shutdown Hook
背景
在开发中,遇到这种情况,多个线程同时工作,突然一个线程遇到了fetal的错误,需要立即终止程序,等人工排查解决了问题之后重新启动。但是这样会有一个问题,程序终止时,其他线程可能正在进行重要操作,比如发一个message到另一个模块,并更新数据库状态。突然终止,可能会让这个操作只完成一半,从而导致数据不一致。
解决方案是:参考数据库Transaction原子性的概念,将这一系列重要操作看作一个整体,要么全部完成,要么全部不完成。为方便表述,我们把这一系列重要操作记为操作X。
当程序即将退出时,查看当前是否有操作X在执行中,
- 如果有,等待其完成然后退出。且期间不再接受新的操作X。如果操作X执行之间过长,终止并回滚所有状态。
- 如果没有,则可以立即退出。
在程序退出的时候,做一些Check,保证已经开始的操作X的原子性,这里就用到了Runtime.ShutdownHook。
什么是Shutdown Hook
Shutdown hook是一个initialized but unstarted thread。当JVM开始执行shutdown sequence时,会并发运行所有registered Shutdown Hook。这时,在Shutdown Hook这个线程里定义的操作便会开始执行。
需要注意的是,在Shutdown Hook里执行的操作应当是不太耗时的。因为在用户注销或者操作系统关机导致的JVM shutdown的例子中,系统只会预留有限的时间给未完成的工作,超时之后还是会强制关闭。
什么时候会调用Shutdown Hook
- 程序正常停止
- Reach the end of program
System.exit
- 程序异常退出
- NPE
- OutOfMemory
- 受到外界影响停止
- Ctrl+C
- 用户注销或者关机
如何使用Shutdown Hook
调用java.lang.Runtime这个类的addShutdownHook(Thread hook)方法即可注册一个Shutdown Hook,然后在Thread中定义需要在system exit时进行的操作。如下:
Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("Do something in Shutdown Hook")));
测试例子
首先,注册了一个Shutdown Hook。
然后,系统Sleep 3秒,模拟进行某些操作。
然后,调用一个空的List,抛出异常,准备结束程序。
在程序将要结束的时候,执行Shutdown Hook中的内容。
public static void main(String[] args)
{
// register shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("Do something in Shutdown Hook")));
// sleep for some time
try {
for (int i=0; i<3; i++) {
System.out.println("Count: " + i + "...");
TimeUnit.MILLISECONDS.sleep(1000);
}
List nullList = new ArrayList<>();
System.out.println("Trying to print null list's first element: " + nullList.get(0).toString());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Ready to exit.");
System.exit(0);
}
结果如下:
Count: 0...
Count: 1...
Count: 2...
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at HookTest.main(HookTest.java:18)
Do something in Shutdown Hook
Process finished with exit code 1
需要注意的点
- 当
System.exit之后,当Shutdown Hook开始执行时,其他的线程还是会继续执行。 - 应当保证
Shutdown Hook的线程安全。 - 在使用多个
Shutdown Hook时一定要特别小心,保证其调用的服务不会被其他Hook影响。否则会出现当前Hook所依赖的服务被另外一个Hook终止了的情况。
链接
Java关闭钩子的应用 - Shutdown Hook的更多相关文章
- java 关闭钩子函数的应用
Runtime.getRuntime().addShutdownHook(shutdownHook); 说明:这个方法的意思就是在jvm中增加一个关闭的钩子,当jvm关闭的时候,会执行系统中已经设置的 ...
- JAVA关闭钩子
JAVA的关闭钩子: 1. 一般应用程序在关闭时都需要做一些善后清理工作,但是用户并不会总是按照推荐的方法关闭应用程序,比如用户直接关闭控制台程序或者按下Ctrl+C结束应用程序,这样就导致清理工作得 ...
- 关闭钩子(shutdown hook)的作用以及在Tomcat中的使用
在很多实际应用环境中,当用户关了应用程序时,需要做一些善后清理工作,但问题是,用户有时并不会按照推荐的方法关闭应用程序,很有可能不做清理工作,例如在Tomcat的部署应用中,通过实例化一个Server ...
- Java Shutdown Hook 场景使用和源码分析
我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复[资料],即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板. 背景 ...
- java的关闭钩子(Shutdown Hook)
Runtime.getRuntime().addShutdownHook(shutdownHook); 这个方法的含义说明: 这个方法的意思就是在jvm中增加一个关闭的钩子,当jv ...
- JAVA虚拟机关闭钩子(Shutdown Hook)
程序经常也会遇到进程挂掉的情况,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码.JAVA中的ShutdownHook提供了比较好的方案. JDK提供了Java.Run ...
- 关闭钩子(shutdown hook)的作用
DK1.3介绍了java.lang.Runtime class的addShutdownHook()方法.如果你需要在你的程序关闭前采取什么措施,那么关闭钩子(shutdown hook)是很有用的. ...
- JAVA 虚拟机钩子
Shutdown Hook Java程序经常也会遇到进程挂掉的情况,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码.JAVA中的ShutdownHook提供了比较好的 ...
- Spark学习:ShutdownHookManager虚拟机关闭钩子管理器
Java程序经常也会遇到进程挂掉的情况,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码. JAVA中的ShutdownHook提供了比较好的方案. JDK提供了Jav ...
随机推荐
- 由button标签在 IE 8.0 下的异常表现引发的一场血案
写在最前的最后:整篇文章絮絮叨叨说了半天,我得出一个最佳实践:和button标签say goodbay,用 a 标签模拟之. 首先看一个在chrome 下的简单demo 这样的布局在组件开发中再常见不 ...
- [网络] DHCP 之 Mac 绑定
[网络] DHCP 之 Mac 绑定 一.瞎扯 今天我们来简单聊聊Mac绑定,这在设备管理时常常被使用. 当然你可能会说我可以设置静态IP啊.先不提静态IP容易冲突.现在我在设置树莓派时就遇到一个问题 ...
- yum 安装和卸载
yum list列出资源库中特定的可以Linux Yum安装或更新以及已经安装的rpm包 安装 yum install 安装包关键字 卸载 yum remove 安装包名
- linux安装scala环境
(安装scala的前提是已经安装好了jdk) 1.下载scala的安装包 wget https://scala-lang.org/files/archive/scala-2.11.0-M2.tgz 2 ...
- Java_异常处理(Exception)
异常:Exception try{ //捕获异常 }catch{ //处理异常 } 异常处理机制: 1.在try块中,如果捕获了异常,那么剩余的代码都不会执行,会直接跳到catch中, 2.在try之 ...
- 04-树5 Root of AVL Tree (25 分)
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child sub ...
- 本地docker镜像上传Docker Hub,并且在腾讯云上pull该镜像,最后运行成功。
1:在docker hub 上注册一个账号(本人直接能注册,有的说不能),然后创建自己的仓库. 2:登录docker hub ( longdbdocker --hub账号,longdb --仓库名称) ...
- docker仓库harbor镜像列表获取命令
2019-03-14 搭建好docker仓库harbor之后,在服务器上获取harbor的所有镜像列表命令 curl -u "harbor账号:密码" -X GET -H &quo ...
- 【文档】五、Mysql Binlog事件结构
这个部分描述了事件被写入binlog或者delay log中的属性.所有的事件有相同的整体结构,也就是包含事件头和事件数据: +===================+ | event header ...
- redis有序集合类型sort set
redis的数据类型之-有序集合 sort set和set类型一样,也是string类型元素的集合,也没有重复的元素,不同的是sort set每个元素都会关联一个权,通过权值可以有序的获取集合中的元素 ...