ProcessBuilder 调用的 Java 进程永远 hibernate

标签 java object concurrency process

我正在开发一个完全用 Java 编写的大型系统。但我也在某些时候通过将 C 程序作为进程运行来与 C 程序通信,通过文件系统向它传达一些输入,然后等待它完成以从中读取结果。现在,除了这个我什么也做不了。我没有时间通过​​ API 或类似的东西链接它们。

在我需要调用此过程两次以获取结果之前,它一直运行良好。我第一次调用时,它工作得很好。然而,对于第二次调用,进程只是挂起!我不知道它是否正在 sleep 并等待信号,但我不明白为什么要这样做。

调用方法如下:

public synchronized boolean processCommand(List command) {
    try { 
        ProcessBuilder pb = new ProcessBuilder(command);
        Process p = pb.start();
        p.waitFor();
        p.destroy();
    } catch(Exception ex) { return false; } 
    return true; 
}

我真的不需要与标准输出或标准输入通信。我只需要进程运行并完成它的工作。但是当调用进程只在我第二次调用它时才等待它时它就会挂起! 我的调用代码只是简单地制作命令列表并从另一个 java 对象调用此方法。

当 C 程序的输入较小时,对方法 processCommand(List command) 的两次调用都可以正常工作。这会是标准输入或标准输出的问题吗?

这简直让我发疯!有人对此有洞察力吗?感谢您的称赞:)

更新:

这是基于@Gray 提到的解决方案:

我只需要耗尽 InputStream 和可能的 ErrorStream:

public synchronized boolean processCommand(List command) {
try { 
    ProcessBuilder pb = new ProcessBuilder(command);
    Process p = pb.start();
    handleStream(p.getInputStream);
    handleStream(p.getErrorStream);
    p.waitFor();
    p.destroy();
} catch(Exception ex) { return false; } 
return true; 

public void handleStream(InputStream input) { 
    try { 
        int c; 
        while( (c=input.read())!= -1) { //Anything }
    } catch(Exception ex) { }
}

最佳答案

尝试按照建议的解决方案 here (原始链接似乎不可用;可以找到存档版本 here ,尽管示例代码的引用链接仍然指向原始站点...)

The best strategy for handling this situation is to kick off a thread just prior to calling waitFor that will interrupt the current thread after a suitable time period. TimerTask was designed for precisely this sort of situation, and waitFor is very responsive to interrupts in most cases. [Follow link in original for an example].

[...]

Java 6 API clearly states that failure to promptly “read the output stream of the subprocess may cause the subprocess to block, and even deadlock.”

[...]

The safe bet for handling this problem today is to explicitly clean up every instance of Process by calling close on each stream made available through Process.getOutputSteam, Process.getInputStream, and Process.getErrorStream, and then call Process.destroy even if the process is already terminated.

关于ProcessBuilder 调用的 Java 进程永远 hibernate ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10365402/

相关文章:

java - 方法具有相同类型的删除

java - 解析Java格式的日期字符串[2012-07-15T20 :55:33+00:00]

javascript - 连接对象不起作用或者我需要将值转换为正确的格式?

javascript - 如何正确从数组中删除对象?

c++ - 我在哪里删除对象?我不在范围内

java - 我们应该将 KeyStore 和 TrustStore 指向同一个 .jks 文件吗?

java - 将带有字母的字符串数组转换为java中的int数组

scala - 测试以确保两个函数同时运行?

ruby-on-rails - 使用并发 Rails 和 Sidekiq 作业的结果

ios - 调度组不为完成 block 工作