我目前正在使用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找出如何做到这一点。
提前谢谢
答案 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 ));