繁体   English   中英

Java - 使用 TimerTask 杀死外部进程

[英]Java - kill external process with TimerTask

我实现了一个方法,其中使用 processBuilder 调用外部程序。 如果外部进程花费的时间超过 5 秒(出于测试原因),我想停止该任务。

当我使用 process.exec() 时,实现工作正常。 但不是 processBuilder.start()

我已经阅读了一些帖子,但它似乎不起作用,因为我无法弄清楚我错过了什么。

方法:

ProcessBuilder processBuilder = new ProcessBuilder("/.../test.bat -a -b -c").redirectErrorStream(true);
Process process = processBuilder.start();

Timer t = new Timer();
TimerTask killer = new TimeoutProcessKiller(process);
t.schedule(killer, 5 * 1000);

BufferedReader lineReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

lineReader.lines().forEach(str -> LOGGER.log(Level.INFO, str));

int lExitCode = process.waitFor();
if (lExitCode == 0) {
    LOGGER.log(Level.INFO, "Process finished successful.");
} else {
    LOGGER.log(Level.INFO, "Process finished not successful.");
}
killer.cancel();

超时进程杀手

public class TimeoutProcessKiller extends TimerTask {
    private Process p;

    public TimeoutProcessKiller(Process p) {
        this.p = p;
    }

    public void run() {
        p.destroy();
    }
}

谢谢你的任何建议。

您的问题很可能是因为您的批处理脚本已经启动了子进程,这些子进程在您的任务破坏了父进程后仍在运行。 更改TimeoutProcessKiller.run()方法以打印出descendants (子进程及其所有子进程),然后也将其杀死。

以下将打印每个尝试杀死它们的PID:

public void run() {
    System.out.println("destroying "+p);
    p.destroy();
    System.out.println("destroying descendants");
    p.descendants().peek(System.out::println).forEach(ProcessHandle::destroy);
    System.out.println("destroyed  "+p);
}

您从Runtime.exec()ProcessBuilder所做的更改不是原因 - 因为Runtime.exec()是对ProcessBuilder的调用。 如果您不使用 STDOUT stream ,后代的问题就会消失(这不是一件明智的事情,因为这会冻结进程),所以您很可能在从Runtime.exec()交换之后添加了BufferedReader lineReader...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM