我还阅读了有关读取错误和输出流的信息;但是,我认为它不适用于这里,或者是吗?
几乎可以肯定是的,它是适用的。尝试使用ProcessBuilder
代替Runtime.exec
并在调用之前读取所有输出waitFor
。例如(省略异常处理,特别是可能在进程实际退出之前waitFor
抛出)InterruptedException
ProcessBuilder pb = new ProcessBuilder(
"cmd", "/c", "start", "/b", "/wait", batchFile);
pb.redirectErrorStream(true);
Process p = pb.start();
IOUtils.closeQuietly(p.getOutputStream());
IOUtils.copy(p.getInputStream(), System.out);
// or alternatively throw away the output using
// IOUtils.copy(p.getInputStream(), NullOutputStream.NULL_OUTPUT_STREAM);
IOUtils.closeQuietly(p.getInputStream());
int returnVal = p.waitFor();
(IOUtils 和 NullOutputStream 来自Apache commons-io)。
要回答标题中的实际问题,如果您的进程即使在正确读取其输出后仍然挂起,您可能需要使用p.destroy()
强制终止进程。您可以定义一个计时器任务,例如
public class TimeoutProcessKiller extends TimerTask {
private Process p;
public TimeoutProcessKiller(Process p) {
this.p = p;
}
public void run() {
p.destroy();
}
}
然后做
// single shared timer instance
Timer t = new Timer();
// for each device
Process p = pb.start();
TimerTask killer = new TimeoutProcessKiller(p);
t.schedule(killer, 30000);
// ... read output stream as before ...
int returnVal = p.waitFor();
killer.cancel();
如果进程运行超过 30 秒,这将导致进程被杀死(调整schedule
调用以更改超时)。