【发布时间】:2014-12-19 14:52:46
【问题描述】:
我正在尝试使用 Process API 从 Java 运行本机可执行文件。本机代码执行长时间运行的计算,可能必须在超时后中断。
理想情况下,我希望使用getInputStream() 接收标准输出,避免使用中间文件。
这是一个难题:
- 不可能首先等待进程终止,然后然后开始读取标准输出。在这种情况下,
waitFor会无限期地等待。 - 如果我首先开始读取标准输出并然后检查退出代码,代码将停止响应
Thread.interrupt()。要查看问题,请参阅以下“最小”示例:
computation.sh 中模拟长时间运行(5 秒)计算的 Bash 代码:
#!/bin/bash
END=$((`date +%s` + 5))
while [ `date +%s` -lt $END ]; do
echo "Heavy computation" > /dev/null
done
echo "Answer is 42"
Test.java 中的 Java 代码在单独的线程中运行 Bash 代码并在 1 秒后中断它:
import java.io.*;
public class Test {
public static void main(String[] args) throws InterruptedException {
Thread waitForProcess = new Thread() {
@Override
public void run() {
Process unixProcess = null;
try {
unixProcess = new ProcessBuilder("./computation.sh").start();
try (BufferedReader stdout = new BufferedReader(
new InputStreamReader(unixProcess.getInputStream()))) {
String line;
// Exactly here, Java stops
// responding to Thread.interrupt():
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
}
int retval = unixProcess.waitFor();
System.out.println("Retval: " + retval);
} catch (InterruptedException ex) {
System.out.println("Computation interrupted.");
} catch (IOException ex) {
System.out.println("IOException: " + ex);
} finally {
if (unixProcess != null) {
unixProcess.destroy();
}
}
}
};
waitForProcess.start();
// Timeout of 1000 ms
waitForProcess.join(1000L);
waitForProcess.interrupt();
// Additional grace time
waitForProcess.join(100L);
// Timeout has occured
if (waitForProcess.isAlive()) {
System.out.println("Timeout occurred");
}
}
}
理想情况下,Java 代码应该打印 Timeout occurred 并在 1 秒后退出。事实上,它等待了全部 5 秒,最终打印出Answer is 42。
有什么帮助吗?
【问题讨论】:
标签: java process timeout interrupt