0

我正在从我的程序中调用一个外部 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) 
            {
            }

我给 SLEEP_TIME 大约 1 分钟,一切正常。突然,对于一个特定的设置,我发现 Sys out (System.out.println) 从生成的过程中花费了非常长的时间。

谁能指出我发生了什么?这两个过程必须是独立的。然而,调用者正在从被调用的进程中读取数据。但是在被调用的进程正在写入的地方,缓冲区应该很大。因此,它不可能被阻止。

我可以在 ProcessBuilder Java 文档中看到这一点:

父进程使用这些流(#getInputStream()、#getErrorStream())向子进程提供输入并从子进程获取输出。由于一些原生平台只为标准输入输出流提供有限的缓冲区大小,未能及时写入子进程的输入流或读取输出流可能会导致子进程阻塞,甚至死锁。

4

3 回答 3

1

看一下NuProcess库,它为衍生进程提供了非阻塞(异步)I/O。 免责声明:我是 NuProcess 的作者

于 2013-11-20T03:30:15.650 回答
0

您需要不断地阅读,而不是阅读立即可用的内容然后睡觉。注意(也)你应该对stdout stderr做同样的事情。

有关使用 a实现此目的的信息,请参阅此问题。StreamGobbler

于 2013-10-30T11:08:47.837 回答
0

这是我在您的情况下所期望的行为。如果一个进程产生stdout(或就此而言的stderr)输出,它不能永远继续这样做,而没有实际对该输出做某事的事情。当您的进程产生输出时,它将被操作系统缓冲,直到该缓冲区已满。您的进程从缓冲区中读取,再次腾出更多空间。如果您的程序没有读取,那么缓冲区将在某个时候填满,并且操作系统将暂停该进程,直到空间可用。

在您的 Java 进程中创建一个线程来读取 STDOUT,并在需要时将其缓冲在 Java 端。另一方面,您可能应该在它到达时对其进行处理,因为它听起来好像有很多。

编辑:基于评论......和其他事情......

DataInputStream.readLine() 已弃用,请勿使用。

而不是有一个while循环:

while (dis.available() != 0) {...}

while ((line = br.readLine()) != null) { ....}

哪里brnew BufferedReader(new InputStreamReader(myProcess.getInputStream()))

于 2013-10-30T11:09:24.383 回答