Javaプロセスの終了メカニズムとShutdown hook

3294 ワード

基本概念
≪プロセスとスレッド|Processand Threads|emdw≫:1つのプロセスに複数のスレッドが含まれ、1つのプロセス内のすべてのスレッドが終了すると、プロセスが終了します.
ユーザー・スレッドとデーモン・スレッド:いずれのユーザー・スレッドも終了せず、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を発行してプロセスを終了する.
リファレンス
https://stackoverflow.com/questions/2541597/how-to-gracefully-handle-the-sigkill-signal-in-java?noredirect=1&lq=1