我正在开发一个大型系统,我完全用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) { }
}
答案 0 :(得分:1)
尝试按照建议的解决方案here
进行操作处理这种情况的最佳策略是在调用waitFor之前启动一个线程,这将在适当的时间段后中断当前线程。 TimerTask专为这种情况而设计,而waitFor在大多数情况下对中断非常敏感。 [关注原文中的链接]。
[...]
Java 6 API明确指出,无法及时“读取子进程的输出流可能导致子进程被阻塞,甚至死锁。”
[...]
今天处理此问题的安全措施是通过在通过Process.getOutputSteam,Process.getInputStream和Process.getErrorStream提供的每个流上调用close来显式清理Process的每个实例,然后调用Process.destroy,即使该过程已经终止。