[英]How to Exit a Process (.exec()) if the External Program hangs
让我解释一下我的软件。 我的软件所做的只是创建 10 个线程并为每个线程分配多个任务。 然后每个线程创建一个运行时进程,该进程将启动一个 cmd 批处理文件,该文件又将启动一个程序,该程序将 telnet 到设备(我有大约 200 个)以轮询其配置。 这是我的流程创建代码:
Process p1 = java.lang.Runtime.getRuntime().exec("cmd /c start /b /wait " + batchFile);
int returnVal = p1.waitFor();
batchFile
是批处理文件的完整路径。 不要误会我的意思,该软件在执行 100% 的情况下都可以正常工作,并且仅在 95% 左右挂起一次,所以我正在尝试为此找到解决方案。 为什么它挂起不是我现在的问题,而是以后如何处理挂机..!
现在的问题是我需要等待进程完成,因为我的 telnet 客户端将写入我稍后将在线程中读取的文件; 因此使用.waitFor()
。 我的问题是如何让线程理解外部程序挂了? 换句话说,我可以给外部程序一些时间限制来完成吗? 如果不是,线程会杀死进程吗?
我还阅读了有关读取错误和输出流的内容; 但是,我认为它不适用于这里,是吗?
我还阅读了有关读取错误和输出流的内容; 但是,我认为它不适用于这里,是吗?
几乎可以肯定,它是适用的。 尝试使用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
调用以更改超时)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.