2012-10-31 33 views
8

我試圖讓一個關機掛鉤在我的Ubuntu服務器上工作,但是我似乎遇到了多個線程的問題。使用基本的ShutdownHook,當我使用kill <PID>殺死進程時,下面的代碼會起作用,這意味着關閉行爲被激活。與多個線程的Java關機掛鉤

public static void main(String[] args) { 
    ShutdownHook shutDown = new ShutdownHook(); 
    shutDown.attachShutDownHook(); 

    while(true){} 
} 

但是有附加線程相同的代碼不

public static void main(String[] args) { 
    ShutdownHook shutDown = new ShutdownHook(); 
    shutDown.attachShutDownHook(); 

    (new Thread() { 
     public void run() { 
      while (true) {} 
     } 
    }).start(); 

    while(true){} 
} 

任何想法?

class ShutdownHook { 

    ShutdownHook() { 
    } 

    public void attachShutDownHook() { 

      Runtime.getRuntime().addShutdownHook(new Thread() { 
        @Override 
        public void run() { 
          System.out.println("Shut down hook activating"); 
        } 
      }); 
      System.out.println("Shut Down Hook Attached."); 

    } 
} 
+0

第二個線程的行爲是什麼?沒有調用關閉行爲,應用程序是否停止?你也說「殺死進程」。你是什​​麼意思?你怎麼終止它? – Gray

+0

第二個線程只是活動線程的一個例子。在我的實際示例中,它正在監聽端口上的連接,並在該程序的整個生命週期中保持活動狀態。我正在用'kill '終止這個過程。上面的第二個程序不能正常工作,所以我在多個線程中丟失了一些東西 – Reese

+0

嘗試在調用'kill'來查看哪些線程仍在運行後運行'jstack '。 – SimonC

回答

0

java.lang.Runtime.addShutdownHook(Thread)註冊一個新的虛擬機來關閉鉤:

Java虛擬機在響應關閉以2種 事件:

  • 程序正常退出,當最後一個非守護進程線程退出或當退出(等同於System.exit)方法時,或者

  • 響應用戶中斷(例如鍵入^ C的 )或系統範圍的事件(如用戶註銷或系統關閉)終止虛擬機。

您的代碼將無限期運行,所以關閉鉤子將永遠不會被調用。

[您的編輯後]

kill你使用哪種?

殺-9是非可捕獲

殺-2可被用於模擬CTRL-C(SIGINT)

+0

我使用'kill ',沒有額外的參數。它應該是可以捕獲的,並且實際上可以在單線程場景中運行 – Reese

3

JVM將不退出,同時還存在着運行非守護線程。嘗試在您的新主題上撥打setDaemon(true)

+0

這似乎並沒有伎倆要麼 – Reese

1

以自己的項目爲例,

我的核心類產生了一大堆工作線程,工作者運行必須完成的事務。

在我的核心課上;

Runtime.getRuntime().addShutdownHook(new ShutdownCleanup()); 

看起來像這樣;

public final class ShutdownCleanup extends Thread() { 
    public void run() { 
     log("waiting for worker threads to finish..."); 
     while(WorkerThread.transactionInProgress()) { 
      Thread.sleep(1000); 
     } 
     //close various sockets and resources 
    } 
} 

我在終端擊中Ctrl+C的時刻,出現log消息。所以shutdown hook立即激活,一旦程序準備好死掉,它就不會運行,而是在收到close或kill請求時立即運行。

因爲這個原因,我相信其他人關於關閉鉤子永遠不會被調用,而仍然存在線程活着的說法是錯誤的。什麼是關機掛鉤的關鍵點,只有在所有東西都已經死亡的情況下才會啓動?

這可能是因爲你正在使用一個強力殺手,比如-9。您是否嘗試過使用Ctrl+CSIGINT正常關機?

+0

是的我嘗試過'kill '沒有參數,而且'CTRL + C'。兩者都在第一個單線程示例中工作,並且只要有多個線程,就不會工作。也許我缺少設置我的線程? – Reese

+0

您是否嘗試過使用上面的'Runtime'方法?我不知道它會有什麼不同,但是可能你將一個鉤子附加到一個線程而不是JVM上......如果可能的話。 – lynks

+0

我正在使用運行系統。我更新了我的原始問題以顯示ShutdownHook本身 – Reese