我正从我的程序调用外部JAVA进程。我正在消耗由这个衍生进程生成的输出,如下所示:
DataInputStream dis = new DataInputStream(new BufferedInputStream(myProcess.getInputStream()));
从线程我正在做以下事情:
while (dis.available() != 0)
{
firstMesg = dis.readLine();
if(firstMesg != null)
{
// processing with the message
//System.out.println(firstMesg);
}
}
try
{
Thread.currentThread().sleep(SLEEP_TIME);
}
catch(Throwable e)
{
}
我在1分钟左右给了SLEEP_TIME,一切正常。突然对于特定的设置我发现Sys out(System.out.println)从产生的过程中花了很长时间。
有人能指出我发生了什么吗?这两个过程必须是独立的。然而,调用者正在从被调用的进程中读取。但是缓冲区应该在调用进程写入的地方很大。所以它不应该被阻止。
我可以在ProcessBuilder Java doc中看到这一点:
父进程使用这些流(#getInputStream(),#getErrorStream())将输入提供给子进程并从子进程获取输出。因为有些原生平台 仅为标准输入和输出流提供有限的缓冲区大小,无法及时写入输入流或读取子流程的输出流可能 导致子进程阻塞,甚至死锁。
答案 0 :(得分:1)
查看NuProcess库,它为衍生进程提供非阻塞(异步)I / O. 免责声明:我是NuProcess的作者。
答案 1 :(得分:0)
您需要持续阅读,而不是阅读立即可用的内容,然后再睡觉。请注意(另外)您应对stdout
和 stderr
执行相同操作。
有关使用StreamGobbler
实现此目的的信息,请参阅this question。
答案 2 :(得分:0)
这是我期望在你的情况下的行为。如果一个进程产生stdout
(或stderr),那么如果没有实际对该输出执行某些操作,它就无法继续这样做。当您的进程产生输出时,它将被操作系统缓冲,直到该缓冲区变满。您的进程从缓冲区中读取,从而再次创建更多空间如果您的程序没有读取,那么缓冲区将在某个时刻填满,操作系统将暂停该过程,直到空间可用。
在Java进程中创建一个线程来读取STDOUT,如果需要,可以在Java端缓冲它。另一方面,你可能应该在它到达时处理它,因为它听起来有很多。
编辑:基于评论...和其他事情......
不推荐使用DataInputStream.readLine(),不要使用它。
而不是使用while循环:
while (dis.available() != 0) {...}
DO
while ((line = br.readLine()) != null) { ....}
其中br
是new BufferedReader(new InputStreamReader(myProcess.getInputStream()))