摘要:在退出时执行必要的挽救措施。在这种情况下,一旦被提供,等待一个进程终止指定的时间。如果进程在该时间限制内没有终止,则通过发出或中的对等方强制终止进程。所以有可能这是在中途执行时发生的。
用途shutdownHook是一种特殊的结构,它允许开发人员插入JVM关闭时执行的一段代码。这种情况在我们需要做特殊清理操作的情况下很有用
在Jboss,Jetty等容器中都可以看到shutdownHook的身影,例如在服务优雅下线一文中的spring-boot-starter-actuator就会触发shutdownHook...
Application正常退出,在退出时执行特定的业务逻辑,或者关闭资源等操作。
虚拟机非正常退出,比如用户按下ctrl+c、OOM宕机、操作系统关闭(kill pid)等。在退出时执行必要的挽救措施。
用法正常退出
public class ShutdownHook { public static void main(String[] args) throws InterruptedException { Runtime.getRuntime().addShutdownHook(new Thread(() -> { try (FileWriter fw = new FileWriter("hook.log")) { // 假设记录日志/或者发送消息 fw.write("完成销毁操作,回收内存! " + (new Date()).toString()); System.out.println("退出程序..."); } catch (IOException e) { e.printStackTrace(); } })); IntStream.range(0, 10).forEach(i -> { try { System.out.println("正在工作..."); Thread.sleep(2_000L); } catch (InterruptedException e) { e.printStackTrace(); } }); } }
当我们运行上面的代码时,会看到在完成main方法的执行时JVM调用shutdownHook。
正在工作... ... 正在工作... 退出程序...
注意事项kill pid方式
虽然编写一个shutdownHook很简单,但是需要了解shutdownHook后面的内部部件才能正确使用。因此,在后续中,将探讨shutdownHook设计背后的一些陷阱。
应用程序无法保证shutdownHook总是运行的
如JVM由于某些内部错误而崩溃,或(Unix / Linux中的kill -9)或TerminateProcess(Windows)),那么应用程序需要立即终止而不会甚至等待任何清理活动。除了上述之外,还可以通过调用Runime.halt()方法来终止JVM,而阻止shutdownHook运行。
shutdownHook可以在完成前强行停止
虽然shutdownHook开始执行,但是在操作系统关闭的情况下,任然可以在完成之前终止它。在这种情况下,一旦SIGTERM被提供,O/S等待一个进程终止指定的时间。如果进程在该时间限制内没有终止,则O/S通过发出SIGTERM(或Windows中的对等方)强制终止进程。所以有可能这是在shutdownHook中途执行时发生的。
因此,建议谨慎地编写shutdownHook,确保它们快速完成,并且不会造成死锁等情况。另外特别注意的是,不应该执行长时间计算或等待用户I/O操作在钩子。
可以有多个shutdownHook,但其执行顺序无法保证
public void addShutdownHook(Thread hook) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission("shutdownHooks")); } ApplicationShutdownHooks.add(hook); } class ApplicationShutdownHooks { /* The set of registered hooks */ private static IdentityHashMaphooks; static synchronized void add(Thread hook) { if(hooks == null) throw new IllegalStateException("Shutdown in progress"); if (hook.isAlive()) throw new IllegalArgumentException("Hook already running"); if (hooks.containsKey(hook)) throw new IllegalArgumentException("Hook previously registered"); hooks.put(hook, hook); } }
通过源码发现,可以注册多个shutdownHook。但是因为它是存储在IdentityHashMap中的,JVM并不能保证其执行顺序。但是可以同时执行所有的shutdownHook
关闭顺序开始后,无法注册/取消注册shutdownHook
一旦关闭顺序是由JVM发起的,将不在允许添加或删除任何现有的shutdownHook,否则抛出IllegalStateException异常。
关闭顺序开始后,只能由Runtime.halt()停止
关闭顺序开始后,只能通过Runtime.halt()(强制终止JVM),可以停止关闭顺序的执行(外部影响除外,如SIGKILL)。
使用shutdownHook需要安全权限
如果我们使用Java Security Managers,则执行添加/删除shutdownHook的代码需要在运行时具有shutdownHooks权限。否则会导致SecurityException。
参考:http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread) "官方文档")
- 说点什么全文代码:https://gitee.com/battcn/battcn-concurent/tree/master/Chapter1-1/battcn-thread/src/main/java/com/battcn/chapter10
个人QQ:1837307557
battcn开源群(适合新手):391619659
微信公众号:battcn(欢迎调戏)
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/67730.html
摘要:匿名函数是我们喜欢的一个重要原因,也是,它们分别消除了很多代码细节上需要命名变量名或函数名的需要。这个匿名函数内,有更多的操作,根据的结果针对目录和文件做了不同处理,而且有递归。 能和微博上的 @响马 (fibjs作者)掰扯这个问题是我的荣幸。 事情缘起于知乎上的一个热贴,诸神都发表了意见: https://www.zhihu.com/questio... 这一篇不是要说明白什么是as...
摘要:在之前,不能为线程单独设置或指定一个默认的,为了设置,需要继承并覆写方法。幸运的是后线程提供了一个方法,用来捕获并处理因线程中抛出的未知异常,以避免程序终止。 在单线程的开发过程中,通常采用try-catch的方式进行异常捕获,但是这种方式在多线程环境中会显得无能为力,而且还有可能导致一些问题的出现,比如发生异常的时候不能及时回收系统资源,或者无法及时关闭当前的连接... 概述 Ja...
摘要:每个对象只有一个锁与之相关联。实现同步则是以系统开销作为代价,甚至可能造成死锁,所以尽量避免滥用。这种机制确保了同一时刻该类实例,所有声明为的函数中只有一个方法处于可执行状态,从而有效避免了类成员变量访问冲突。 synchronized是JAVA语言的一个关键字,使用 synchronized 来修饰方法或代码块的时候,能够保证多个线程中最多只有一个线程执行该段代码 ... 概述 ...
摘要:的作用是为其他线程的运行提供服务,比如说线程。在某些平台上,指定一个较高的参数值可能使线程在抛出之前达到较大的递归深度。参数的值与最大递归深度和并发程度之间的关系细节与平台有关。 今天研究了下Java线程基础知识,发现以前太多知识知识略略带过了,比较说Java的线程机制,在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程),以及构造器中的s...
摘要:如果有其它线程调用了相同对象的方法,那么处于该对象的等待池中的线程就会全部进入该对象的锁池中,从新争夺锁的拥有权。 wait,notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视,而本文则是对这些关键字的使用进行描述。 存在即合理 在java中,每个对象都有两个池,锁池(monitor)和等待池(waitset),每个...
阅读 2925·2023-04-26 02:22
阅读 2285·2021-11-17 09:33
阅读 3126·2021-09-22 16:06
阅读 1062·2021-09-22 15:54
阅读 3530·2019-08-29 13:44
阅读 1904·2019-08-29 12:37
阅读 1315·2019-08-26 14:04
阅读 1904·2019-08-26 11:57