3

我们正在尝试使用 调用 Windows 中的外部程序Runtime.getRuntime().exec(...),但这似乎会导致死锁。外部进程异步启动,但不久后停止执行任何操作。当我停止 Java 线程时,外部进程继续,所以它必须以某种方式等待 Java 线程。这是我们目前的相关代码:

try {
    Process process = Runtime.getRuntime().exec(System.getProperty("user.dir") + "program.exe");
    BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); //Read output of program from its buffer.
    String line;
    while((line = input.readLine()) != null) {
        System.out.println(line);
    }
    process.waitFor();
} catch(IOException e) {
    e.printStackTrace();
} catch(InterruptedException e) {
    e.printStackTrace();
}

程序在输出 3313 个字节后停止。我们尝试了各种清空缓冲区的方法,因为这似乎有时会导致这个问题。

Java 程序正在等待外部程序完成(process.waitFor()),直到我终止 Java 程序,外部程序才完成,因此导致死锁。我们怎样才能防止这种情况发生?我们无法访问外部程序的源代码。

4

2 回答 2

1

终于找到了罪魁祸首。显然,运行时进程不仅提供了输入流(Process#getInputStream),还提供了错误流(Process#getErrorStream)。错误流也被填满,因为外部程序给出了一些关于文件格式错误的错误。

解决方案包括创建一个新的可运行类,该类从单独线程中的流中读取。然后主线程将创建该对象的两个实例,一个从输入流中读取,另一个从错误流中读取,然后让两个实例异步运行它们的线程。这样,两个流同时被读取,主线程将调用Process#waitFor.

我希望这也能帮助那些偶然发现这个问题的人。

于 2013-10-10T23:15:37.480 回答
0

Java 程序正在等待外部程序完成(process.waitFor()),直到我终止 Java 程序,外部程序才完成,因此导致死锁。我们怎样才能防止这种情况发生?

你无法阻止它。根据Java文档

如果子进程尚未终止,则调用线程将被阻塞,直到子进程退出。

于 2013-10-10T10:59:36.883 回答