Одновременно использовать стандартный вывод из внешнего процесса - PullRequest
0 голосов
/ 22 июня 2009

Существует ли потокобезопасный способ одновременного потребления stdout из внешнего процесса с использованием ProcessBuilder в Java 1.6?

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

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

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

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

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

Ответы [ 3 ]

2 голосов
/ 22 июня 2009

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

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

1 голос
/ 22 июня 2009

Да.

Я написал некоторый код, который запускает трудоемкое задание (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();
1 голос
/ 22 июня 2009

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...