簡體   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