【发布时间】:2019-11-06 02:15:48
【问题描述】:
在我的 Java 11(Debian 下的 openjdk 11.0.3 2019-04-16)程序中,我使用 ProcessBuilder 来启动外部命令。外部命令可能会挂起,因此我需要它在给定时间后超时。
所以我使用应该返回的p.waitFor(time, unit)
如果进程已经退出,则为 true;如果在进程退出之前等待时间已过,则为 false。
ProcessBuilder pb = new ProcessBuilder(externalCommand);
// Merges the error stream with the standard output stream
pb.redirectErrorStream(true);
Process p = pb.start();
Date start = new Date();
BufferedReader br = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String tempLine;
/**
* We only want the first 10 lines otherwise it will print thousands of
* useless lines (always the same)
*/
int nbOfLinesInlogs = 10;
while ((tempLine = br.readLine()) != null) {
// We only report errors to the user
if (tempLine.toLowerCase().startsWith("error") && nbOfLinesInlogs > 0) {
Level level = Level.WARNING;
System.err.println("External command output : " + tempLine);
// There was an error
errorDetected = true;
nbOfLinesInlogs--;
}
}
if (p.waitFor(10l,
TimeUnit.NANOSECONDS)) {
long elapsedInMillis = new Date().getTime() - start.getTime();
System.err.println("External process succeeded and took " + elapsedInMillis + " ms");
// prints Externalprocess succeeded and took 15327 ms
...
}
else {
System.err.println("External process timed out");
// This is never printed!
throw new InterruptedException(
"External process timed out!");
}
但是,该过程永远不会超时并打印出它花费了 15 秒,尽管它应该在 10 纳秒后超时(这只是一个测试,以检查超时是否按预期工作)。我还尝试了 µs、ms 和 s,结果相同。
如何让进程在超时时返回 false ?
任何帮助表示赞赏,
【问题讨论】:
-
我认为
...后面没有隐藏 15 秒的计算价值,在Date start = new Date();和p.waitFor(10l, TimeUnit.NANOSECONDS)之间? -
您正在处理您正在创建的
Process的输入流和错误流吗?根据我对ProcessBuilder的经验,不正确处理Process流可能会导致有问题的行为。请记住,您需要在单独的线程中处理流 - 一个用于输入流,另一个用于错误流。 -
@HelloWorld 亚伦的意思是,如果在你开始等待之前有一些事情需要很长时间,那么这个过程实际上可能已经结束了,因为这 15 秒在你开始这个过程和你开始等待的时间。
-
它不在一个单独的线程中 为什么不呢?正如我之前评论的那样,根据我的经验,它必须位于单独的线程中。做起来并不难,网上有很多例子展示了如何做。
-
因为你使用了一个while循环,一旦输入关闭,它只会返回false。由于您的输入仅在进程终止时关闭,因此您的检查 (waitFor) 会在进程结束后发生。
标签: java