Java process.getInputStream() 没有啥可读的,死锁子

Posted

技术标签:

【中文标题】Java process.getInputStream() 没有啥可读的,死锁子【英文标题】:Java process.getInputStream() has nothing to read, deadlocks childJava process.getInputStream() 没有什么可读的,死锁子 【发布时间】:2011-04-14 23:43:13 【问题描述】:

我遇到了一些进程包装问题,它只发生在 Windows XP 中。这段代码在 Windows 7 中完美运行。我真的很困惑为什么 XP 中的流是空的。我也尝试过使用 Process.Exec() 的 String[] 版本,它没有任何区别。

我正在使用以下类来读取进程的 STDOUT 和 STDERR(每个流的实例):


import java.util.*;
import java.io.*;

public class ThreadedStreamReader extends Thread
 InputStream in;
 Queue messageQueue;

 public ThreadedStreamReader(InputStream s, Queue q)
 
  in = s;
  messageQueue = q;
 

 public void run()
 
  try
  
   BufferedReader r = new BufferedReader(new InputStreamReader(in));
   String line = null;
   while((line = r.readLine()) != null)
   
    synchronized(messageQueue)
    
     messageQueue.add(line);
    
   

  catch(Exception e)
  
   System.err.println("Bad things happened while reading from a stream");
  
 

我在这里使用它:


Process p = Runtime.getRuntime().exec("test.exe");
Queue&ltString&gt q = new LinkedList&ltString&gt();

ThreadedStreamReader stdout = new ThreadedStreamReader(p.getInputStream(), q);
ThreadedStreamReader stderr = new ThreadedStreamReader(p.getErrorStream(), q);

stdout.start();
stderr.start();

while(true)

    while(q.size() > 0)
    
        System.out.println(q.remove());
    

有人有什么想法吗?谢谢!

编辑:添加同步

编辑:就像更新一样,父流读取器的读取操作被阻止。如果我使用任务管理器杀死子进程,它们会从流的关闭中读取 null。

【问题讨论】:

+1 提出了一个很好的详细问题,表明您已经考虑了这里可能出现的潜在问题。 坐在这里上网搜索答案后,我偶然发现了这个问题。我还没有找到解决方案,只有一种解决方法,但至少我已经启动并运行了。我传递给程序的参数之一导致它挂起。我取出了参数,这对于我正在尝试做的事情并不是最佳的,但程序不再挂起。同样的参数也适用于我的 Win7 机器,所以我什至不认为这是其中的一部分。哦,好的,谢谢你的帮助! 你删除了什么样的参数?我在 Java 中遇到了一些奇怪而愚蠢的死锁问题(都有一个共同点:从 System.in 中读取) 【参考方案1】:

你需要使用线程安全的数据结构;我不认为 LinkedList 是线程安全的。

【讨论】:

我已经更新了要同步的代码。它仍然有同样的问题。 :\【参考方案2】:

让我印象深刻的一个错误是LinkedList is not synchronized,但您正试图在 2 个线程中写入它。

要记住的另一件事是Process.getInputStream() 返回进程的stdout 流,因此您应该将当前名为stdin 的变量重命名为stdout 以防止混淆。

【讨论】:

是的,我对“stdin”的使用感到困惑。从 Java 程序的角度来看,它是一个输入流,但从 Process 的角度来看,它是标准输出。 我已将标准输入更改为标准输出并添加同步。【参考方案3】:

Vista 之前的 Windows 操作系统中存在已知错误,加载 DLL 会导致 IO 挂起。

例如见http://weblogs.java.net/blog/kohsuke/archive/2009/09/28/reading-stdin-may-cause-your-jvm-hang和https://connect.microsoft.com/VisualStudio/feedback/details/94701/loadlibrary-deadlocks-with-a-pipe-read

我不确定这是否是您遇到的问题,但它可能是相关的。

另外,我隐约记得从非控制台 Windows 应用程序获取有效标准输入和标准输出的一些问题。如果您对“test.jar”的调用使用的是“javaw”而不是“java”,那么这也可能是导致问题的原因。

【讨论】:

哦,我只是以test.jar为例。不过,很高兴知道这一点。 阅读 System.in 通常是个问题。我对这个问题的回答中有更多指向 SUN-ug 报告的链接:***.com/questions/3836780/…【参考方案4】:

由于一些原生平台只为标准输入输出流提供有限的缓冲区大小,未能及时写入子进程的输入流或读取输出流可能会导致子进程阻塞,甚至死锁。

【讨论】:

以上是关于Java process.getInputStream() 没有啥可读的,死锁子的主要内容,如果未能解决你的问题,请参考以下文章

Java 布尔运算

java [Java] Java常用代码#java

Java - 35 Java 实例

Java While 循环

Java 字符串

Java If ... Else