[英]How to Exit a Process (.exec()) if the External Program hangs
Let me explain my software.让我解释一下我的软件。 What my software simply does is that it creates 10 threads and assigns a number of tasks to each thread.我的软件所做的只是创建 10 个线程并为每个线程分配多个任务。 Each thread then creates a Runtime Process that will start a cmd batch file which in turn will start a program that will telnet to a device (I have about 200 of them) to poll its configuration.然后每个线程创建一个运行时进程,该进程将启动一个 cmd 批处理文件,该文件又将启动一个程序,该程序将 telnet 到设备(我有大约 200 个)以轮询其配置。 Here is the code for my process creation:这是我的流程创建代码:
Process p1 = java.lang.Runtime.getRuntime().exec("cmd /c start /b /wait " + batchFile);
int returnVal = p1.waitFor();
batchFile
is the full path of the batch file. batchFile
是批处理文件的完整路径。 Don't get me wrong, the software works fine up to 100% of the execution and it hanged ONLY ONE TIME at about 95%, so I'm trying to find a solution for that.不要误会我的意思,该软件在执行 100% 的情况下都可以正常工作,并且仅在 95% 左右挂起一次,所以我正在尝试为此找到解决方案。 Why it hanged is not my issue now, but rather how to deal with hangups later on..!为什么它挂起不是我现在的问题,而是以后如何处理挂机..!
Now the problem is that I need to wait for the process to finish because my telnet client will write to a file that I will read later on in the thread;现在的问题是我需要等待进程完成,因为我的 telnet 客户端将写入我稍后将在线程中读取的文件; and hence the use of the .waitFor()
.因此使用.waitFor()
。 My question is how can I get the thread to understand that the external program hanged?我的问题是如何让线程理解外部程序挂了? In other words, can I give the external program some time limit to finish;换句话说,我可以给外部程序一些时间限制来完成吗? and if it does not the thread will kill the process?如果不是,线程会杀死进程吗?
Also I have read about reading the error and output streams;我还阅读了有关读取错误和输出流的内容; however, I don't think it is applicable here, or is it?但是,我认为它不适用于这里,是吗?
Also I have read about reading the error and output streams;我还阅读了有关读取错误和输出流的内容; however, I don't think it is applicable here, or is it?但是,我认为它不适用于这里,是吗?
Almost certainly yes, it is applicable.几乎可以肯定,它是适用的。 Try using ProcessBuilder
instead of Runtime.exec
and read all the output before calling waitFor
.尝试使用ProcessBuilder
而不是Runtime.exec
并在调用waitFor
之前读取所有输出。 For example (exception handling omitted, in particular waitFor
may throw InterruptedException
before the process actually exited)例如(省略异常处理,特别是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 and NullOutputStream are from Apache commons-io ). (IOUtils 和 NullOutputStream 来自Apache commons-io )。
To answer the actual question in the title, if your process still hangs even after properly reading its output, you may need to use p.destroy()
to forcibly terminate the process.要回答标题中的实际问题,如果您的进程即使在正确读取其输出后仍然挂起,您可能需要使用p.destroy()
强行终止该进程。 You could define a timer task something like你可以定义一个类似的计时器任务
public class TimeoutProcessKiller extends TimerTask {
private Process p;
public TimeoutProcessKiller(Process p) {
this.p = p;
}
public void run() {
p.destroy();
}
}
and then do然后做
// 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();
This will cause the process to be killed if it has been running for more than 30 seconds (adjust the schedule
call to change the timeout).如果进程已经运行超过 30 秒,这将导致进程被终止(调整schedule
调用以更改超时)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.