Java process.getInputStream () читать нечего, блокирует дочерний процесс - PullRequest
8 голосов
/ 21 сентября 2010

У меня проблема с некоторыми процессами, и это происходит только в Windows XP.Этот код прекрасно работает в Windows 7. Я действительно озадачен тем, почему потоки пусты в XP.Я также пытался использовать String [] версию Process.Exec (), и это не имело никакого значения.

Я использую следующий класс для чтения из процесса '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());
    }
}

У кого-нибудь есть какие-нибудь идеи?Спасибо!

Редактировать: добавлена ​​синхронизация

Редактировать: Так же, как и обновление, читатели родительского потока блокируются при выполнении операции чтения.Если я убиваю дочерние процессы с помощью диспетчера задач, они читают ноль с момента закрытия потока.

Ответы [ 4 ]

1 голос
/ 28 февраля 2012

Поскольку некоторые собственные платформы предоставляют ограниченный размер буфера только для стандартных входных и выходных потоков, невозможность оперативной записи входного потока или чтения выходного потока подпроцесса может привести к блокировке подпроцесса и даже к взаимной блокировке.

1 голос
/ 21 сентября 2010

Одна ошибка, которая меня поражает, это то, что LinkedList не синхронизируется , но вы пытаетесь записать его в 2 потока.

Еще одна вещь, о которой следует помнить: Process.getInputStream() возвращает поток stdout процесса, поэтому вам следует переименовать переменную, называемую stdin, в stdout, чтобы избежать путаницы.

1 голос
/ 21 сентября 2010

Существуют известные ошибки в операционных системах до Vista, где загрузка DLL может привести к зависанию ввода-вывода.

например. см 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 из неконсольных приложений Windows. Если ваш вызов test.jar использует javaw вместо java, то это также может быть причиной вашей проблемы.

1 голос
/ 21 сентября 2010

Вам необходимо использовать потокобезопасную структуру данных; Я не думаю, что LinkedList является потокобезопасным.

...