ProcessBuilder正在对生成的进程进行锁定

时间:2013-10-30 11:03:26

标签: java multithreading process

我正从我的程序调用外部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())将输入提供给子进程并从子进程获取输出。因为有些原生平台 仅为标准输入和输出流提供有限的缓冲区大小,无法及时写入输入流或读取子流程的输出流可能 导致子进程阻塞,甚至死锁。

3 个答案:

答案 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) { ....}

其中brnew BufferedReader(new InputStreamReader(myProcess.getInputStream()))