2009-02-24 37 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));