1. 程式人生 > >Java 程序的退出機制與Shutdown hook

Java 程序的退出機制與Shutdown hook

基本概念

程序與執行緒:一個程序包含多個執行緒,一個程序中所有執行緒都退出後,該程序才會退出。

使用者執行緒與守護執行緒:任一使用者執行緒未退出,JVM程序不退出,當所有使用者執行緒都退出時,
守護執行緒執行緒自動退出。

Shutdown hook:程序退出時執行的鉤子,主要用來清理釋放資源使程序友好的退出。為了避免強制退出JVM可能產生的各種問題,我們可以採用Shutdownhook、發出訊號的方式,主動的通知JVM退出,並在JVM關閉前,執行應用程式的一些掃尾工作,進一步保證應用程式可以安全的退出。

Linux下與結束程序相關的訊號量

名稱 編號 功能
SIGINT 2 中斷(同 Ctrl + C)會觸發觸發shutdownhook
SIGKILL 9 終止程序,強制殺死程序
SIGTERM 15 終止程序,會先釋放自己的資源,觸發shutdownhook然後終止程序

Shutdown hook例子

    public class TestShutdownHook {

      public static void main(final String[] args) throws InterruptedException {
        Runtime.getRuntime().addShutdownHook(new
Thread() { @Override public void run() { System.out.println("Shutdown hook ran!"); } }); while (true) { Thread.sleep(1000); } } }

在linux環境下執行如上述程式碼,當通過kill -15 pid,kill -2 pid結束該Java程序時ShutdownHook會被呼叫。但Kill -9 pid不會觸發ShutdownHook呼叫。當通過kill -9去結束一個Java程序時,則需要通過另一個程式來判斷程序是否被關閉。例如通過shell指令碼。

#!/bin/bash java TestShutdownHook wait # notify your other app that you quit echo "TestShutdownHook quit"

不友好的shutdown hook

shutdown hook內部陷入死迴圈,或被block住,會使程序無法退出。

public class Main {

  public static void main(String[] args) throws Throwable {
    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
      while (true) {
        try {
          TimeUnit.SECONDS.sleep(1);
          System.out.println("shutdown");
        }catch (Exception e) {

        }
      }
    }));
  }
}

這種情況結合外部程式或指令碼可以先發出kill -15,kill -2 如果一段時間內檢測到程序未關閉,那麼再發出kill -9來結束程序。

參考