1 回答

TA貢獻1848條經(jīng)驗 獲得超6個贊
在您的第一個示例中,主線程退出,然后 JVM 檢測到?jīng)]有剩余的非守護進程線程并將啟動 JVM 關(guān)閉。此時,加入主線程沒有問題,因為它甚至在關(guān)閉之前就已經(jīng)結(jié)束了。
在您的第二個變體中,主線程,即main
通過執(zhí)行方法的線程env -> CallStaticVoidMethod(…)
正忙于執(zhí)行jvm -> DestroyJavaVM()
。由于該函數(shù)等待關(guān)閉處理程序的完成而您的關(guān)閉處理程序等待該線程的完成,因此您會遇到死鎖。
您也可以使用純 Java 代碼獲得類似的行為。當您放置System.exit(0);
在main
方法的末尾,讓主線程啟動關(guān)閉并等待其完成時,您會遇到類似的死鎖。
通常,您不應join
在關(guān)閉處理程序中執(zhí)行操作。這些處理程序應該盡快清理并返回。
或者,正如文檔所說:
關(guān)閉鉤子在虛擬機生命周期的一個微妙時刻運行,因此應該進行防御性編碼。特別是,它們應該被編寫為線程安全的,并盡可能避免死鎖。他們也不應該盲目依賴可能已經(jīng)注冊了自己的關(guān)閉鉤子的服務,因此他們自己可能會在關(guān)閉過程中。例如,嘗試使用其他基于線程的服務(例如 AWT 事件分派線程)可能會導致死鎖。
添加回答
舉報