【问题标题】:Concurrency issue between waiting for a process and reading the stream?等待进程和读取流之间的并发问题?
【发布时间】:2013-02-26 09:02:03
【问题描述】:

我使用ProcessBuilder 来运行进程。我通过在线程池 (Executors.newCachedThreadPool()) 中提交相应的可运行对象来处理输入/输出流。
我得到了结果,但时不时地我什么也没得到。
例如,如果我这样做:cmd \C dir 到流程构建器我得到了dir 的结果,但有时我什么也没有得到(尽管结果似乎从处理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){}  
}

在不起作用的情况下,它会打印Finished reading 521。但我尝试通过pw 而不是sb 获得结果。
pw is PrintWriter pw = PrintWriter(outputStream);` 我在可运行文件中传递了它

更新 2:
似乎:status = process.waitFor(); 在处理输入流的可运行对象完成之前返回之前。怎么会这样?
我在 javadoc 中读到:
the calling thread will be blocked until the subprocess exits。那么这是否意味着我可以在使用 I/O 流之前返回

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

【问题讨论】:

  • 如果一个进程调用另一个进程,第一个进程可能会过早返回 - 正常行为。
  • 这不是关于过早返回。而是关于在输出流被消耗之前返回

标签: java multithreading outputstream executorservice processbuilder


【解决方案1】:

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

因此,process.waitFor(); 可能会在读取所有缓冲输出之前返回(即使有大量输出时也是如此)。

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

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

编辑 一种解决方案是将 waitFor() 移动到流 gobbler 并将 gobbler 转换为 Callable 然后您可以将其提交给执行程序并使用 Future API ( example) 获取结果。

【讨论】:

  • 那么我应该如何修改我的代码来处理这个问题?我现在只做waitFor 并且我的流阅读器中的代码已发布
  • 在包含流处理程序的线程上调用waitFor 然后join()。或者让流处理程序在 while() 循环之外调用 waitFor() 以将两者放在同一个位置。
  • 1)Stream handler被提交给一个executor。我怎么join?2)stream handler怎么调用waitFor?结果应该是传递给线程等待完成过程
  • 您将不得不使用不同的策略。例如,给流处理程序一个可以处理结果而不是等待的实例的句柄。或者将结果推送到一个队列中,让一个线程在这个队列中等待工作。
  • 如何将Runnable 转换为Callable 并为每个流gobler 执行get
猜你喜欢
  • 1970-01-01
  • 2015-06-15
  • 1970-01-01
  • 2012-03-27
  • 2017-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-01
相关资源
最近更新 更多