Что делать с ненужными потоками из внешнего процесса? - PullRequest
1 голос
/ 13 января 2011

Когда я выполняю команду в отдельном процессе, например, с помощью метода Runtime.getRuntime().exec(...), чей JavaDoc сообщает:

Executes the specified command and arguments in a separate process.

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

Если мы считаем, что этот процесс вообще не производит вывода (например, потому что все сообщения об ошибках и стандартный вывод перенаправляются в / dev / null и все коммуникации осуществляются с использованием файлов / сокетов / чего угодно), что мне нужно делать с входной поток?

Должен ли я иметь один (или два?) Потока Java, работающие даром, пытаясь прочитать stdout / stderr?

Как правильно обращаться с долгоживущим внешним процессом, порожденным из Java-программы, которая вообще не производит stdout / stderr?

EDIT

По сути, я обертываю сценарий оболочки в другой сценарий оболочки, который обязательно перенаправляет все в / dev / null . Я почти уверен, что мой Un * x был бы несовместим, если бы мой «внешний» сценарий оболочки (тот, который перенаправляет все в / dev / null) все равно генерировал бы что-либо на stdout или stderr . И все же я считаю ошеломляющим, что у меня как-то должны быть потоки, запущенные в течение жизненного цикла приложения "на пустую голову". Действительно уму непостижимо.

Ответы [ 2 ]

1 голос
/ 13 января 2011

Я считаю, что правильный способ справиться с вводом и выводом процесса, если вы не заинтересованы в них, - это быстро закрыть их. Если дочерний процесс впоследствии попытался вызвать read или write для stdin или stdout соответственно, то будет сгенерировано исключение IOException. Дочерний процесс несет ответственность за то, что он не может читать или писать.

Большинство процессов будут игнорировать тот факт, что они не могут писать и молча отбрасывать и писать. Это верно в Java, где System.out является PrintWriter, поэтому любые исключения IOException, генерируемые stdout, игнорируются. Это почти то же самое, что происходит, когда вы перенаправляете вывод в / dev / null - весь вывод игнорируется.

Звучит так, как будто вы прочитали API на процессах и почему важно читать / писать процессу, если он ожидает, что он выполняет какие-либо записи или чтения самостоятельно. Но еще раз повторюсь, проблема в том, что некоторые ОС выделяют только очень ограниченные буферы для (в частности) стандартного вывода, поэтому важно либо не допустить заполнения этих буферов. Это означает либо быстрое чтение любого вывода дочернего процесса, либо уведомление ОС о том, что вам не требуется вывод процесса и что он может освободить все имеющиеся ресурсы, и отклонение любых дальнейших попыток записи в стандартный вывод или чтения из стандартного ввода (скорее чем просто висеть, пока ресурсы не станут доступными).

1 голос
/ 13 января 2011

Если все так, как вы говорите, то вы, вероятно, можете их игнорировать.

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

...