我遇到了一些流程包装问题,而且只发生在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<String> q = new LinkedList<String>();
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。
答案 0 :(得分:1)
您需要使用线程安全的数据结构;我认为Linked List不是线程安全的。
答案 1 :(得分:1)
我遇到的一个错误是LinkedList
is not synchronized,但你试图用2个帖子写信给它。
要记住的另一件事是Process.getInputStream()
返回流程的stdout
流,因此您应该将当前名为stdin
的变量重命名为stdout
以防止混淆。
答案 2 :(得分:1)
在Vista之前的Windows操作系统中存在已知错误,其中加载DLL会导致IO挂起。
e.g。请参阅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
我不确定这是不是你正在进行的,但它可能是相关的。
另外,我模糊地回忆起从非控制台窗口应用程序获取有效stdin和stdout的一些问题。如果你对'test.jar'的调用是使用'javaw'而不是'java',那么这也可能是你问题的原因。
答案 3 :(得分:1)
由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此无法及时写入输入流或读取子进程的输出流可能导致子进程阻塞,甚至死锁。