运行时 addShutdownHook(Thread hook) 方法注册一个新的虚拟机关闭挂钩。 Java 虚拟机响应两种事件而关闭。

  • 程序正常退出,当最后一个非守护线程退出时或退出 (等效地,调用 System.exit) 方法,或者

  • 虚拟机因响应用户中断而终止,例如键入 ^C 或系统范围的事件,例如用户注销或系统关闭。

关闭挂钩只是一个已初始化但未启动的线程。当虚拟机开始其关闭序列时,它将以某种未指定的顺序启动所有已注册的关闭挂钩,并让它们同时运行。当所有挂钩完成后,如果启用了退出时终结,它将运行所有未调用的终结器。最后,虚拟机将停止。请注意,守护线程将在关闭序列期间继续运行,如果通过调用 exit 方法启动关闭,则非守护线程也会继续运行。

声明

以下是 java.lang.Runtime.addShutdownHook() 方法

public void addShutdownHook(Thread hook) 

参数

hook - 已初始化但未启动的 Thread 对象。

返回值

此方法不返回值。

异常

  • IllegalArgumentException - 如果指定的钩子已经注册,或者可以确定该钩子已经运行或已经运行。

  • IllegalStateException - 如果虚拟机已处于关闭过程中。

  • SecurityException - 如果存在安全管理器并且它拒绝 RuntimePermission("shutdownHooks")。

示例 1

在此示例中,我们通过扩展 Thread 类来创建一个 CustomThread 类。该线程对象将用作 JVM 关闭挂钩。 CustomThread 类具有 run() 方法实现。在主类 TestThread 中,我们通过向其传递一个线程对象,使用 Runtime.getRuntime().addShutdownHook() 方法添加了一个关闭钩子。在输出中,您可以验证当程序即将退出时是否调用了 CustomThread run() 方法。

package com.yxjc123;

class CustomThread extends Thread {
   public void run() {
      System.out.println("JVM is shutting down.");
   }
}

public class TestThread {
   public static void main(String args[]) throws InterruptedException {
      try {
         // 将 CustomThread 注册为关闭钩子
         Runtime.getRuntime().addShutdownHook(new CustomThread());
         //打印程序的状态
         System.out.println("Program is starting...");
         //导致线程休眠3秒
         System.out.println("Waiting for 3 seconds...");
         Thread.sleep(3000);
         //打印程序正在关闭
         System.out.println("Program is closing...");
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
} 

输出

Program is starting...
Waiting for 3 seconds...
Program is closing...
JVM is shutting down. 

示例 2

在此示例中,我们通过实现 Runnable 接口来创建一个 CustomThread 类。该线程对象将用作 JVM 关闭挂钩。 CustomThread 类具有 run() 方法实现。在主类 TestThread 中,我们通过向其传递一个线程对象,使用 Runtime.getRuntime().addShutdownHook() 方法添加了一个关闭钩子。在输出中,您可以验证当程序即将退出时是否调用了 CustomThread run() 方法。

package com.yxjc123;

class CustomThread implements Runnable {
   public void run() {
      System.out.println("JVM is shutting down.");
   }
}

public class TestThread {
   public static void main(String args[]) throws InterruptedException {
      try {
         //将CustomThread注册为关闭钩子
         Runtime.getRuntime().addShutdownHook(new Thread(new CustomThread()));
         //打印程序的状态
         System.out.println("Program is starting...");
         //导致线程休眠3秒
         System.out.println("Waiting for 3 seconds...");
         Thread.sleep(3000);
         //打印程序正在关闭
         System.out.println("Program is closing...");
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
} 

输出

Program is starting...
Waiting for 3 seconds...
Program is closing...
JVM is shutting down. 

示例 3

我们可以删除关闭钩子也可以使用removeShutdownHook()。在此示例中,我们通过实现 Runnable 接口创建一个 CustomThread 类。该线程对象将用作 JVM 关闭挂钩。 CustomThread 类具有 run() 方法实现。在主类 TestThread 中,我们通过向其传递一个线程对象,使用 Runtime.getRuntime().addShutdownHook() 方法添加了一个关闭钩子。作为最后一条语句,我们使用 Runtime.getRuntime().removeShutdownHook() 方法删除钩子

package com.yxjc123;

class CustomThread implements Runnable {
   public void run() {
      System.out.println("JVM is shutting down.");
   }
}

public class TestThread {
   public static void main(String args[]) throws InterruptedException {
      try {
         Thread hook = new Thread(new CustomThread());
         //将消息注册为关闭钩子
         Runtime.getRuntime().addShutdownHook(hook);
         //打印程序的状态
         System.out.println("Program is starting...");
         //导致线程休眠3秒
         System.out.println("Waiting for 3 seconds...");
         Thread.sleep(3000);
         //打印程序正在关闭
         System.out.println("Program is closing...");
		  Runtime.getRuntime().removeShutdownHook(hook);
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
} 

Output

Program is starting...
Waiting for 3 seconds...
Program is closing...