序言:

每一个Java程序都可以为JVM增加一个关闭钩子。JVM将在关闭之前执行关闭钩子中的指令。

问题:

一个程序可能需要在退出前执行一些指令。程序可能由于下列原因而退出:

  • 所有的线程已经执行完毕

  • 调用System.exit()

  • 用户输入Ctrl+C

  • 系统级关闭或用户注销

适用场景:

  • 保存应用状态,例如,当多数IDE退出时,它们将记忆最后的视图有哪些。

  • 关闭某些数据库连接。

  • 将应用关闭的消息发送给系统管理员。

解决方案:

关闭钩子支持所有这些场景。应用可以增加一个关闭钩子,JVM将在应用退出时调用它。

抽象层次的概念:

将所有的指令(Java代码)写入一个线程的run()内,并且调用java.lang.Runtime.addShutdownHook(Thread t)。该方法将这个线程注册为JVM的关闭钩子。在关闭JVM的时候,JVM将并行地运行这些钩子(线程将在JVM关闭的时候启动)。

代码示例:

public class AddShutdownHookSample {

     public void attachShutDownHook() {

         Runtime.getRuntime().addShutdownHook(new Thread() {

              @Override

              public void run() {

                   System.out.println("Inside Add Shutdown Hook");

              }

         });

         System.out.println("Shut Down Hook Attached.");

     }

     public static void main(String[] args) {

         AddShutdownHookSample sample = new AddShutdownHookSample();

         sample.attachShutDownHook();

         System.out.println("Last instruction of Program....");

         System.exit(0);

     }

}

  

输出:

Shut Down Hook Attached.

Last instruction of Program....

Inside Add Shutdown Hook

  

现在明白了如何使用addShutDownHook。如果需要可以增加多个关闭钩子,但是需要注意的是,钩子是并行地运行,所以注意并发避免死锁发生。

在应用中实现关闭钩子:

  • 关闭钩子的数量:关闭钩子的数量没有限制,如果需要可以增加多个关闭钩子。看看run()的修改版本:

public void attachShutDownHook() {

         for (int i = 0; i < 10; i++) {

              Runtime.getRuntime().addShutdownHook(new Thread() {

                   @Override

                   public void run() {

                       System.out.println("Inside Add Shutdown Hook : "

                                 + Thread.currentThread().getName());

                   }

              });

         }

     }

  

如上,我们增加了10个关闭钩子。

  • 何时增加关闭钩子:任何时候!!!在任何情况下都可以增加一个关闭钩子,只要在JVM关闭之前。如果试图在JVM开始关闭后注册一个关闭钩子,将抛出一个带有”Shutdown is progress”消息的IllegalStateException。

  • 增加相同的钩子:不能增加相同的钩子。如果这样做了,将抛出带有”Hook previously registered”消息的IllegalArgumentException。

  • 注销钩子:调用Runtime.removeShutdownShook(Thread hook)可以注销一个钩子。

注意:大多数时候,使用匿名内部类来注册关闭钩子,既然我们没有持有这些类的可用引用,我们也无法使用要注销钩子的匿名内部类,因为我们需要将它们传递给removeShutdownHook(Thread hook)。

  • 注意并发:万一不止一个关闭钩子,它们将并行地运行,并容易引发线程问题,例如死锁。Java Doc对该方法是这样描述的: /**

* A <i>shutdown hook</i> is simply an initialized but unstarted thread.

* When the virtual machine begins its shutdown sequence it will start all

* registered shutdown hooks in some unspecified order and let them run

* concurrently. When all the hooks have finished it will then run all

* uninvoked finalizers if finalization-on-exit has been enabled. Finally,

* the virtual machine will halt. Note that daemon threads will continue to

* run during the shutdown sequence, as will non-daemon threads if shutdown

* was initiated by invoking the <tt>{@link  #exit exit}</tt> method.

*/

翻译过来:

关闭钩子只是一个已初始化但尚未启动的线程。虚拟机开始启用其关闭序列时,它会以某种未指定的顺序启动所有已注册的关闭钩子,并让它们同时运行。运行完所有的钩子后,如果已启用finalization-on-exit,那么虚拟机接着会运行所有未调用的finalizers。最后,虚拟机会暂停。注意,关闭序列期间会继续运行守护线程,如果通过调用exit方法来发起关闭序列,那么也会继续运行非守护线程。

  • 关闭钩子的可靠性:JVM将在退出的时候尽最大努力来执行关闭钩子,但是不保证一定会执行。例如,当在Linux中使用-kill命令时,或在Windows中终结进程时,由于本地代码被调用,JVM将立即退出或崩溃。

  • 注意钩子的时间消耗:需要注意的重点之一是,关闭钩子不应该花费过多时间。考虑这样一个场景,当用户从操作系统中注销,操作系统花费非常有限的时间就正常退出了,因此在这样样的场景下JVM也应该尽快退出。

结论:

Runtime.addShutdownHook(Thread hook)是非常方便的工具,它提供从JVM中优雅退出的一个通用机制。尤其是在类似服务器实现这样的大型应用中。当然,应该小心使用。

参考:

http://download.oracle.com/javase/1.5.0/docs/guide/lang/hook-design.html

http://download.oracle.com/javase/6/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)

原文地址:http://hellotojavaworld.blogspot.com/2010/11/runtimeaddshutdownhook.html

Runtime.addShutdownHook()(译)的更多相关文章

  1. 利用 java.lang.Runtime.addShutdownHook() 钩子程序,保证java程序安全退出

    以前在开发时只知道依靠数据库事务来保证程序关闭时数据的完整性. 但有些时候一个业务上要求的原子操作,不一定只包括数据库,比如外部接口或者消息队列.此时数据库事务就无能为力了. 这时我们可以依靠java ...

  2. Runtime.addShutdownHook的用法

    原文出处:http://kim-miao.iteye.com/blog/1662550.感谢作者的无私分享. 一.Runtime.addShutdownHook理解 在看别人的代码时,发现其中有这个方 ...

  3. Runtime.addShutdownHook用法

    一.什么是ShutdownHook? 在Java程序中可以通过添加关闭钩子,实现在程序退出时关闭资源.平滑退出的功能. 使用Runtime.addShutdownHook(Thread hook)方法 ...

  4. 关于jvm钩子 Runtime.getRuntime().addShutdownHook

    转自: http://www.cnblogs.com/nexiyi/p/java_add_ShutdownHook.html 在线上Java程序中经常遇到进程程挂掉,一些状态没有正确的保存下来,这时候 ...

  5. Java Runtime 详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt219 那就首先说点Runtime类吧,他是一个与JVM运行时环境有关的类,这 ...

  6. Java Runtime.exec()的使用

    Sun的doc里其实说明还有其他的用法: exec(String[] cmdarray, String[] envp, File dir) Executes the specified command ...

  7. [转]Java中Runtime.exec的一些事

    0 预备知识 1 不正确的调用exitValue 2不正确的调用waitFor 3 一种可接受的调用方式 4 调用认为是可执行程序的时候容易发生的错误 5 window执行的良好示例 6 不良好的重定 ...

  8. Runtime.getRuntime()

    1转自:https://www.aliyun.com/jiaocheng/849282.html 那就首先说点Runtime类吧,他是一个与JVM运行时环境有关的类,这个类是Singleton的.我说 ...

  9. Java Runtime.exec()用法

    转自:https://www.cnblogs.com/mingforyou/p/3551199.html Java Runtime.exec()的使用 Sun的doc里其实说明还有其他的用法: exe ...

随机推荐

  1. [Go] golang的MPG调度模型

    MPG模式运行状态11)当前程序有三个M,如果三个M都在一个cpu运行,就是并发,如果在不同的cpu运行就是并行2)M1,M2,M3正在执行一个G,M1的协程队列有三个,M2的协程队列有三个,M3的协 ...

  2. 阅读高翔的RGBD-SLAM博文笔记

    目录 高翔的RGBD-SLAM笔记 前端VO: 后端优化 高翔的RGBD-SLAM笔记 RGBD相机的特点: 使用RGBD相机中的深度这一维信息,以及相机的针孔成像模型,相机的内参,可以将二维点恢复成 ...

  3. 上云测试,这些关键点你get 到没有

    导读,先从云化说起,再谈谈云化形态下,除了常规的功能测试,云化的测试,还需要有几个必须要get到的硬核指标,最后在分别详解这些关键点硬核指标是什么,和如何测试呢.这是个值得深思的问题,希望所有测试人都 ...

  4. mysql的floor()报错注入方法详细分析

    刚开始学习sql注入,遇见了 select count(*) from table group by floor(rand(0)*2); 这么条语句.在此做个总结. (更好的阅读体验可访问 这里 ) ...

  5. tensorflow模型量化实例

    1,概述 模型量化应该是现在最容易实现的模型压缩技术,而且也基本上是在移动端部署的模型的毕竟之路.模型量化基本可以分为两种:post training quantizated和quantization ...

  6. JS中key-value存取

    获取Key 在代码中,遇到需要单独提取对象的key值时可使用 Object.keys(object) object是你需要操作的对象Object.keys()会返回一个存储对象中所有key值的数组获取 ...

  7. 【使用篇二】SpringBoot服务端数据校验(8)

    对于任何一个应用而言,客户端做的数据有效性验证都不是安全有效的,而数据验证又是一个企业级项目架构上最为基础的功能模块,这时候就要求我们在服务端接收到数据的时候也对数据的有效性进行验证.为什么这么说呢? ...

  8. 不使用已下载的package pip 安装 & 出现time out error

    pip install XX + --no-cache-dir 安装出现time out error时: pip --default-timeout=10000 install XX

  9. [RN] React Native FlatList 选中后 状态没有立即发生改变,而在下一次生效的问题

    React Native FlatList 选中后 状态没有立即发生改变,而在下一次生效的问题 解决关键: 给 FlatList 添加 extraData={this.state} 非常关键,如果不设 ...

  10. 【转】Java代码编译过程简述

    转载:https://blog.csdn.net/fuzhongmin05/article/details/54880257. 代码编译是由Javac编译器来完成,流程如下图1所示: 图1 Javac ...