[英]Concurrency issue between waiting for a process and reading the stream?
我使用ProcessBuilder
来运行进程。 我通过提交在线程池( Executors.newCachedThreadPool()
)中处理它们的相应runnable来处理输入/输出流。
我得到了结果但是偶尔我什么也得不到。
例如,如果我执行: cmd \\C dir
到进程构建器,我得到dir
的结果,但有时我没有得到任何东西(尽管结果似乎从处理process.getInputStream
的runnable回来)。
我该怎么调试呢? 它间歇地出现了。 使用相同的代码,当我执行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){}
}
在不起作用的情况下,它打印Finished reading 521
。 但我试图通过pw
得到结果,而不是sb
。
pw
是PrintWriter pw = PrintWriter(outputStream);`我在runnable中传递的
更新2:
看来: status = process.waitFor();
在处理输入流的runnable完成之前返回。 怎么会发生这种情况?
我在javadoc中读到:
the calling thread will be blocked until the subprocess exits
。 那么这是否意味着我可以在消耗I / O流之前返回?
更新3:
在Ruby中似乎是同样的问题
即过程结束和消耗输出之间存在一些竞争条件
是。 进程之间的stdio是缓冲的(通常是4KB缓冲区)。 进程A写入缓冲区并存在。 进程B有两个线程; 一个等待A的结束而另一个从A读取输出。无法确定哪个线程首先执行。
因此有可能(甚至可能在有大量输出时) process.waitFor();
在读取所有缓冲输出之前返回。
请注意,刷新对此没有帮助,因为它只是确保A已写入所有内容。 没有办法“强制”B以类似的方式读取数据。
因此,只有在从输入流中读取EOF时,才应记住退出状态并将该过程视为“完全终止”。
编辑一个解决方案是将waitFor()
移动到流gobbler并将gobbler转换为Callable
,然后您可以将其提交给执行程序并使用Future
API( 示例 )来获取结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.