摘要:在退出時執行必要的挽救措施。在這種情況下,一旦被提供,等待一個進程終止指定的時間。如果進程在該時間限制內沒有終止,則通過發出或中的對等方強制終止進程。所以有可能這是在中途執行時發生的。
用途shutdownHook是一種特殊的結構,它允許開發人員插入JVM關閉時執行的一段代碼。這種情況在我們需要做特殊清理操作的情況下很有用
在Jboss,Jetty等容器中都可以看到shutdownHook的身影,例如在服務優雅下線一文中的spring-boot-starter-actuator就會觸發shutdownHook...
Application正常退出,在退出時執行特定的業務邏輯,或者關閉資源等操作。
虛擬機非正常退出,比如用戶按下ctrl+c、OOM宕機、操作系統關閉(kill pid)等。在退出時執行必要的挽救措施。
用法正常退出
public class ShutdownHook { public static void main(String[] args) throws InterruptedException { Runtime.getRuntime().addShutdownHook(new Thread(() -> { try (FileWriter fw = new FileWriter("hook.log")) { // 假設記錄日志/或者發送消息 fw.write("完成銷毀操作,回收內存! " + (new Date()).toString()); System.out.println("退出程序..."); } catch (IOException e) { e.printStackTrace(); } })); IntStream.range(0, 10).forEach(i -> { try { System.out.println("正在工作..."); Thread.sleep(2_000L); } catch (InterruptedException e) { e.printStackTrace(); } }); } }
當我們運行上面的代碼時,會看到在完成main方法的執行時JVM調用shutdownHook。
正在工作... ... 正在工作... 退出程序...
注意事項kill pid方式
雖然編寫一個shutdownHook很簡單,但是需要了解shutdownHook后面的內部部件才能正確使用。因此,在后續中,將探討shutdownHook設計背后的一些陷阱。
應用程序無法保證shutdownHook總是運行的
如JVM由于某些內部錯誤而崩潰,或(Unix / Linux中的kill -9)或TerminateProcess(Windows)),那么應用程序需要立即終止而不會甚至等待任何清理活動。除了上述之外,還可以通過調用Runime.halt()方法來終止JVM,而阻止shutdownHook運行。
shutdownHook可以在完成前強行停止
雖然shutdownHook開始執行,但是在操作系統關閉的情況下,任然可以在完成之前終止它。在這種情況下,一旦SIGTERM被提供,O/S等待一個進程終止指定的時間。如果進程在該時間限制內沒有終止,則O/S通過發出SIGTERM(或Windows中的對等方)強制終止進程。所以有可能這是在shutdownHook中途執行時發生的。
因此,建議謹慎地編寫shutdownHook,確保它們快速完成,并且不會造成死鎖等情況。另外特別注意的是,不應該執行長時間計算或等待用戶I/O操作在鉤子。
可以有多個shutdownHook,但其執行順序無法保證
public void addShutdownHook(Thread hook) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission("shutdownHooks")); } ApplicationShutdownHooks.add(hook); } class ApplicationShutdownHooks { /* The set of registered hooks */ private static IdentityHashMaphooks; static synchronized void add(Thread hook) { if(hooks == null) throw new IllegalStateException("Shutdown in progress"); if (hook.isAlive()) throw new IllegalArgumentException("Hook already running"); if (hooks.containsKey(hook)) throw new IllegalArgumentException("Hook previously registered"); hooks.put(hook, hook); } }
通過源碼發現,可以注冊多個shutdownHook。但是因為它是存儲在IdentityHashMap中的,JVM并不能保證其執行順序。但是可以同時執行所有的shutdownHook
關閉順序開始后,無法注冊/取消注冊shutdownHook
一旦關閉順序是由JVM發起的,將不在允許添加或刪除任何現有的shutdownHook,否則拋出IllegalStateException異常。
關閉順序開始后,只能由Runtime.halt()停止
關閉順序開始后,只能通過Runtime.halt()(強制終止JVM),可以停止關閉順序的執行(外部影響除外,如SIGKILL)。
使用shutdownHook需要安全權限
如果我們使用Java Security Managers,則執行添加/刪除shutdownHook的代碼需要在運行時具有shutdownHooks權限。否則會導致SecurityException。
參考:http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread) "官方文檔")
- 說點什么全文代碼:https://gitee.com/battcn/battcn-concurent/tree/master/Chapter1-1/battcn-thread/src/main/java/com/battcn/chapter10
個人QQ:1837307557
battcn開源群(適合新手):391619659
微信公眾號:battcn(歡迎調戲)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67730.html
摘要:匿名函數是我們喜歡的一個重要原因,也是,它們分別消除了很多代碼細節上需要命名變量名或函數名的需要。這個匿名函數內,有更多的操作,根據的結果針對目錄和文件做了不同處理,而且有遞歸。 能和微博上的 @響馬 (fibjs作者)掰扯這個問題是我的榮幸。 事情緣起于知乎上的一個熱貼,諸神都發表了意見: https://www.zhihu.com/questio... 這一篇不是要說明白什么是as...
摘要:在之前,不能為線程單獨設置或指定一個默認的,為了設置,需要繼承并覆寫方法。幸運的是后線程提供了一個方法,用來捕獲并處理因線程中拋出的未知異常,以避免程序終止。 在單線程的開發過程中,通常采用try-catch的方式進行異常捕獲,但是這種方式在多線程環境中會顯得無能為力,而且還有可能導致一些問題的出現,比如發生異常的時候不能及時回收系統資源,或者無法及時關閉當前的連接... 概述 Ja...
摘要:每個對象只有一個鎖與之相關聯。實現同步則是以系統開銷作為代價,甚至可能造成死鎖,所以盡量避免濫用。這種機制確保了同一時刻該類實例,所有聲明為的函數中只有一個方法處于可執行狀態,從而有效避免了類成員變量訪問沖突。 synchronized是JAVA語言的一個關鍵字,使用 synchronized 來修飾方法或代碼塊的時候,能夠保證多個線程中最多只有一個線程執行該段代碼 ... 概述 ...
摘要:的作用是為其他線程的運行提供服務,比如說線程。在某些平臺上,指定一個較高的參數值可能使線程在拋出之前達到較大的遞歸深度。參數的值與最大遞歸深度和并發程度之間的關系細節與平臺有關。 今天研究了下Java線程基礎知識,發現以前太多知識知識略略帶過了,比較說Java的線程機制,在Java中有兩類線程:User Thread(用戶線程)、Daemon Thread(守護線程),以及構造器中的s...
摘要:如果有其它線程調用了相同對象的方法,那么處于該對象的等待池中的線程就會全部進入該對象的鎖池中,從新爭奪鎖的擁有權。 wait,notify 和 notifyAll,這些在多線程中被經常用到的保留關鍵字,在實際開發的時候很多時候卻并沒有被大家重視,而本文則是對這些關鍵字的使用進行描述。 存在即合理 在java中,每個對象都有兩個池,鎖池(monitor)和等待池(waitset),每個...
閱讀 2931·2023-04-26 02:22
閱讀 2290·2021-11-17 09:33
閱讀 3134·2021-09-22 16:06
閱讀 1072·2021-09-22 15:54
閱讀 3536·2019-08-29 13:44
閱讀 1914·2019-08-29 12:37
閱讀 1321·2019-08-26 14:04
閱讀 1914·2019-08-26 11:57