Java 程序的退出機制與Shutdown hook
阿新 • • 發佈:2019-02-19
基本概念
程序與執行緒:一個程序包含多個執行緒,一個程序中所有執行緒都退出後,該程序才會退出。
使用者執行緒與守護執行緒:任一使用者執行緒未退出,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來結束程序。