转 http://501565246-qq-com.iteye.com/blog/1733575
博客分类:
在很多环境下,在关闭应用程序的时候需要做一些清理工作。问题在于,用户并不是经常的按照要求的流程来退出
Java提供了一种优雅的方式供程序员来使用,这样可以保证清理代码的执行。使用一个关闭钩子(shutdown hool)来保证清理代码一定会被执行。在Java中,虚拟机遇到两种事件的时候会关闭虚拟机:· 应用程序正常退出如System.exit方法被调用或者最后一个非守护退出。 · 用户突然强制终止虚拟机,例如键入CTRL+C或者在关闭Java程序之前从系统注销。当关闭的时候,虚拟机会有以下两个步骤:1. 虚拟机启动所有注册的关闭钩子。关闭钩子是实现在Runtime上面注册的线程。所有的关闭钩子会被同时执行直到完成。2. 虚拟机调用所有的未被调用的finalizers一个关闭钩子是java.lang.Thread类的子类,可以如下创建一个关闭钩子:· 写一个类继承Thread类 · 提供你的实现类中的run方法。该方法是应用程序被关闭的时候要提交的代码,无论是正常退出还是非正常退出。 · 在你的应用程序中,初始化一个关闭钩子 · 在当前的Runtime上使用addShutdownHook方法来注册该关闭钩子。例子
一个简单的类名为ShutdownHookDemo以及一个Thread类的子类名为ShutdownHook类。注意其run方法仅仅会打印出一些语句在控制台上,但是,你可以在其中插入任何你想要执行的语句。- public class ShutdownHookDemo {
- public void start() {
- System.out.println("Demo");
- ShutdownHook ShutdownHook = new ShutdownHook();
- Runtime.getRuntime().addShutdownHook(ShutdownHook);
- }
- public static void main(String[] args) {
- ShutdownHookDemo demo = new ShutdownHookDemo();
- demo.start();
- try {
- System.in.read();
- } catch (Exception e) {
- }
- }
- }
- class ShutdownHook extends Thread {
- public void run() {
- System.out.println("Shutting down");
- }
- }
在初始化一个ShutdownHookDemo对象之后,主方法调用start方法。
Start方法创建一个关闭钩子并在当前Runtime中注册。ShutdownHook ShutdownHook = new ShutdownHook();Runtime.getRuntime().addShutdownHook(ShutdownHook); Tomcat中的关闭钩子在org.apache.catalina.startup.Catalina类中找到它,该类负责启动服务器对象以管理其它组件。在该类中有一个内部类CatalinaShutdownHook继承了java.lang.Thread类,在该类的run方法中调用了服务器的stop方法- protected class CatalinaShutdownHook extends Thread {
- public void run() {
- if (server != null) {
- try {
- ((Lifecycle) server).stop();
- } catch (LifecycleException e) {
- System.out.println("Catalina.stop: " + e);
- e.printStackTrace(System.out);
- if (e.getThrowable() != null) {
- System.out.println("----- Root Cause -----");
- e.getThrowable().printStackTrace(System.out);
- }
- }
- }
- }
- }
该关闭钩子在Catalina实例启动的时候被初始化并添加到Runtime中。