等待进程和读取流之间的并发问题?

Jim*_*Jim 7 java multithreading outputstream executorservice processbuilder

我用a ProcessBuilder来运行进程.我通过提交在线程池(Executors.newCachedThreadPool())中处理它们的相应runnable来处理输入/输出流.
我得到了结果但是偶尔我什么也得不到.
例如,如果我这样做:cmd \C dir对于流程构建器,我得到了dir返回的结果,但有时我没有得到任何东西(尽管结果似乎从处理它的runnable中恢复process.getInputStream).
我该怎么调试呢?它间歇地出现了.使用相同的代码,我没有遇到任何问题new Thread(runnable).start().它在我切换到线程池后开始发生.

更新:
我想我找到了一些东西:
我在以下方面做了以下事情Runnable:

 try {  
    while ( (line = br.readLine()) != null) {  
            pw.println(line);  
                sb.append(line);   
    }  
    System.out.println("Finished reading "+sb.length());  
} catch (IOException e) {             
    e.printStackTrace();  
}  
finally{  
   pw.flush();     
  try{
    isr.close();  
  }catch(Exception e){}  
}
Run Code Online (Sandbox Code Playgroud)

在不起作用的情况下,它打印Finished reading 521.但我试图通过pw而不是得到结果sb.
pw是PrintWriter pw = PrintWriter(outputStream);`我传递给runnable

更新2:
似乎:处理输入流的runnable完成之前status = process.waitFor();返回.怎么会发生这种情况? 我在javadoc中读到:.那么这是否意味着我可以消耗I/O流之前返回?

the calling thread will be blocked until the subprocess exits

更新3:
Ruby中似乎是同样的问题
在进程结束和消耗输出之间存在一些竞争条件

Aar*_*lla 1

是的。进程之间的stdio是有缓冲的(通常是4KB缓冲区)。进程A写入缓冲区并存在。进程B有两个线程;一个等待 A 的末尾,另一个读取 A 的输出。无法确定哪个线程先执行。

因此,有可能(甚至在有大量输出时)process.waitFor();在读取所有缓冲输出之前返回。

请注意,刷新在这里没有帮助,因为它只是确保 A 已写入所有内容。没有办法以类似的方式“强制”B读取数据。

因此,您应该记住退出状态,并仅当您从输入流读取 EOF 时才将进程视为“完全终止”。

编辑一种解决方案是将waitFor()gobbler 移入流 gobbler 并将 gobbler 转换为 a Callable,然后您可以将其提交给执行器并使用FutureAPI(示例)来获取结果。