如果Quartz Scheduler死了,我该如何停止它启动的子Java进程?

时间:2009-02-24 21:59:27

标签: java multithreading process

我目前正在使用Quartz Scheduler替代我们的Windows 2003 Server Box上的Cron。 我有两个需要在新VM中启动的特定作业,所以我使用Java 5中的ProcessBuilder对象来获取我的“Process”对象。 我遇到的问题是我们的Quartz Scheduler JVM停止运行时,单独的JVM中的2个作业仍在继续。

        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找出如何做到这一点。

提前谢谢

2 个答案:

答案 0 :(得分:3)

如果Quartz JVM正常退出,你可以破坏finally块中的进程。这可以避免需要关闭钩子。在异常JVM终止时,可能无法执行关闭挂接。运行时javadocs状态,

  

如果虚拟机中止,则无法保证是否将运行任何关闭挂钩。

这是修改后的代码(我添加了一个超时和一个方法调用来等待进程退出)

    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

答案 1 :(得分: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 ));