ProcessBuilder调用的Java进程将永远休眠

时间:2012-04-28 16:29:17

标签: java object concurrency process

我正在开发一个大型系统,我完全用Java编写。但我也在某种程度上与C程序通信,将其作为一个进程运行,通过文件系统向它传递一些输入,然后等待它完成从中读取结果。就目前而言,除此之外我什么也做不了。我没有时间通过​​API或类似的东西链接它们。

这很有效,直到我需要两次调用此过程才能获得结果。一个我做第一次调用,它工作得很好。但是,对于第二次调用,该过程就会挂起!如果它正在睡觉并等待信号我不会,但我不明白为什么它应该这样做。

以下是执行调用的方法:

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; 
}

我真的不需要与stdout或stdin进行通信。我只需要运行并完成其工作的过程。但它只是在调用进程等待它时才挂起,这是我第二次调用它! 我的调用代码只是简单地创建命令列表并从另一个java对象调用此方法。

当C程序的输入较小时,对方法processCommand(List命令)的两次调用都能正常工作。这会是stdin或stdout的一些问题吗?

这只会让我发疯!有人对此有所了解吗?我感谢您的赞扬:)。

更新:

以下是基于@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) { }
}

1 个答案:

答案 0 :(得分:1)

尝试按照建议的解决方案here

进行操作
  

处理这种情况的最佳策略是在调用waitFor之前启动一个线程,这将在适当的时间段后中断当前线程。 TimerTask专为这种情况而设计,而waitFor在大多数情况下对中断非常敏感。 [关注原文中的链接]。

     

[...]

     

Java 6 API明确指出,无法及时“读取子进程的输出流可能导致子进程被阻塞,甚至死锁。”

     

[...]

     

今天处理此问题的安全措施是通过在通过Process.getOutputSteam,Process.getInputStream和Process.getErrorStream提供的每个流上调用close来显式清理Process的每个实例,然后调用Process.destroy,即使该过程已经终止。