2009-02-24 53 views
3

我目前在我們的Windows 2003 Server Box上使用Quartz Scheduler作爲Cron的替代品。 我有兩個特定的作業需要在新的VM中啓動,所以我使用Java 5中的ProcessBuilder對象來獲取我的「Process」對象。 我遇到的問題是當我們的Quartz Scheduler JVM停止時,單獨JVM中的2個作業繼續運行。如果Quartz Scheduler死亡,我該如何阻止它啓動的子進程?

 Process process = Runtime.getRuntime().exec(command); 
     try 
     { 
      while (true) 
      { 

       Thread thread1 = new Thread(new ReaderThread(process.getInputStream())); 
       Thread thread2 = new Thread(new ReaderThread(process.getErrorStream())); 

       thread1.start(); 
       thread2.start(); 

       thread1.join(); 
       thread2.join(); 

當我的Quartz Scheduler關聯的父JVM死亡時,有沒有辦法殺死這些線程?即使我知道一種方法可以通過手動方式從不同的進程中殺死它們,我也可以通過Quartz瞭解如何實現。

預先感謝您

回答

3

如果Quartz JVM正常退出,您可以在finally塊中銷燬進程。這可以避免需要關閉掛鉤。關閉掛鉤可能無法在異常JVM終止時執行。運行時javadoc狀態,

如果虛擬機中止,則不能保證是否會運行任何關閉掛接。

這裏是修改後的代碼(我已經添加了超時而一個方法調用,以便等待進程退出)

private static final long TIMEOUT_MS = 60000; 
    Process process = Runtime.getRuntime().exec(command); 
    try 
    { 
     while (true) 
     { 

      Thread thread1 = new Thread(new ReaderThread(process.getInputStream())); 
      Thread thread2 = new Thread(new ReaderThread(process.getErrorStream())); 

      thread1.start(); 
      thread2.start(); 

      process.waitFor(); 
      thread1.join(TIMEOUT_MS); 
      thread2.join(TIMEOUT_MS); 
      ... 
     } 
    } finally { 
     process.destroy(); 
    } 

一般我發現過程從Java催生是笨重並不是很有彈性,因爲您可能已經發現需要兩個ReaderThreads。特別是,凍結的子進程很難從Java中終止。作爲最後的手段,您可以使用Windows「taskkill」命令,在命令行或計劃任務核彈的過程:

的taskkill/IM MySpawnedProcess.exe

2

您可以使用關閉掛鉤。

class ProcessKiller extends Thread { 
    private Process process = null; 
    public ProcessKiller(Process p) { 
    this.process = p; 
    } 


    public void run() { 
    try { 
     p.destroy(); 
    } catch (Throwable e) {} 
    } 
} 

Runtime.getRuntime().addShutdownHook(new ProcessKiller(process));