2009-06-22 2 views
0

Есть ли поточно-безопасный способ одновременного использования stdout из внешнего процесса с использованием ProcessBuilder в Java 1.6?Одновременно потреблять stdout из внешнего процесса

Предпосылки: Мне нужно вызвать pbzip2, чтобы распаковать большие файлы в stdout и обрабатывать каждую строку при распаковке файла (pbzip2 использует несколько процессоров, в отличие от других реализаций).

Логический подход заключается в создании дочернего потока в петле через InputStream (т.е. стандартный вывод, вы просто не любите именование?) Следующим образом:

while((line = reader.readLine()) != null) 
{ 
    // do stuff 
} 

Однако разархивирования медленно, так то, что мне действительно нужно, это метод reader.readLine, чтобы спокойно ждать следующей строки, чтобы стать доступной, а не выйти.

Есть ли хороший способ сделать это?

+1

Reader.readLine() делает именно то, что вы хотите. Выходит слишком рано? – akarnokd

+0

Нет, документация, которую я имел, не указывала, будет ли она ждать или нет, так что мне стало интересно, насколько это было поточно-безопасным - например, если бы время просто закончилось, readLine подумал бы о потоке закрыто. – Rob

ответ

2

Вы должны иметь возможность обернуть ваш входной поток InputStreamReader и BufferedReader. Затем вы можете позвонить readLine() и это будет блокироваться по мере необходимости.

Обратите внимание, что у вас должен быть соответствующий считыватель для stderr. Вам не нужно ничего с этим делать, но вам нужно будет использовать поток stderr, иначе ваш порочный процесс может блокироваться. См. this answer для ссылок и т. Д.

1

У вас более или менее есть решение самостоятельно. Вы просто создаете новый поток, который читает следующую строку в цикле из потока вашего внешнего процесса и обрабатывает эту строку.

readLine() будет блокировать и ждать, пока не будет доступна вся новая строка. Если вы используете многоядерную/процессорную машину, ваш внешний процесс может с радостью продолжать распаковывать, пока поток обрабатывает строку. По крайней мере, распаковка может продолжаться до тех пор, пока не будут заполнены трубы/буферы OS.

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

метод ReadLine спокойно ждать следующую строку (ы), чтобы стать доступными, вместо выхода

обнаружит, что это именно то, что Readline должен делать, он просто будет блокироваться, пока целая линия не является доступный.

1

Да.

Я написал код, который запускает трудоемкую работу (ffmpeg) в процессе (порожденной обработчиком процесса), и он, в свою очередь, запускает мой класс OutputStreamReader, который является расширением Thread, который потребляет stdio, и делает это с ним магия.

Улов (для меня) перенаправлял поток ошибок. Вот мой фрагмент кода:

 procbbuilder.redirectErrorStream(true); 
     proc = pb.start(); 
     err = new MyOutputStreamReader(this, proc.getInputStream()); //extenion of thread 
     err.start(); 

     int exitCode = proc.waitFor(); 
Смежные вопросы