Можете ли вы переназначить system.in, system.out и system.err в потоки Java? - PullRequest
0 голосов
/ 13 февраля 2011

У меня есть старый код C ++, который использует stdio для ввода и вывода. Код также порождает новые процессы посредством разветвления. Он сопоставляет stdio с каждым новым процессом, поэтому каждый сеанс получает свои соответствующие данные.

Я смотрю на использование потоков в Java для создания дочерних процессов. Тем не менее, я застрял, когда дело доходит до выяснения, как переназначить System.in, System.out и System.err на дочерние потоки при создании.

Может ли кто-нибудь указать мне правильное направление, если это возможно?

Ответы [ 4 ]

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

порождение потока - это не то же самое, что порождение процесса.когда вы создаете поток в java (и c ++), он разделяет то же пространство памяти, что и spawner (то есть они используют одни и те же потоки sdio).если вы хотите порождать новый процесс в java, вы должны использовать Runtime.exec (), а затем вам придется вручную передавать поток ввода-вывода в новый процесс, java не поддерживает совместное использование потоков ввода-вывода через границы процесса..

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

Простой ответ не состоит в том, чтобы писать свой код как прямой доступ к System.out / in / err. Вместо этого имейте InputStream и два OutputStream, переданные в конструктор вашего объекта. Затем объект работает непосредственно с этими объектами и не зависит от того, на что они действительно отображаются. Чтобы получить доступ к print() и println(), вы передадите OutputStream в конструктор PrintStream.

Затем, основываясь на том, что вы на самом деле хотите сделать, вы можете вызвать конструктор с помощью System.out или некоторого FileOutputStream.

0 голосов
/ 13 февраля 2011

Я бы рекомендовал использовать отдельные процессы или явно назначить PrintStream каждому потоку.

Однако можно пересылать записи в System.out в разные места для каждого потока, даже если каждый поток видит один и тот же объект для System.out. В вашем коде запуска вы бы вызвали System.setOut (PrintStream) с пользовательским PrintStream. Этот PrintStream переопределяет все методы print и write. В этих методах он будет искать PrintStream потока с InheritableThreadLocal и перенаправлять вызов метода к нему.

0 голосов
/ 13 февраля 2011

В Java нет функции fork (), но есть ProcessBuilder и Runtime.exec () для запуска новых процессов (объектов класса Process).Вы можете думать об этом как о паре fork () / exec (), но без возможности выполнять что-то промежуточное, например dup2 ().Это означает, что вы не можете перенаправить stdio дочернего процесса, но вы можете явно записать что-то в его stdin и прочитать из его stdout и stderr, используя соответствующие методы Process или, если быть точным, соответствующие методы потоков ввода / выводавозвращается методами getInputStream () / getOutputStream () / getErrorStream () класса Process.Это может быть допустимым обходным решением, если вы хотите иметь процессы вместо потоков.

Если вы хотите использовать потоки, то все они используют один и тот же stdio.Вы можете перенаправить его, но это будет бессмысленно, поскольку перенаправление повлияет на все потоки.Вы можете использовать своего рода имитацию IPC с потоками, используя пользовательские реализации InputStream / OutputStream, или вы можете захотеть взглянуть на пару PipedInputStream / PipedOutputStream.На самом деле их можно использовать для установки чего-то вроде канала IPC, возможно, в сочетании с BufferedInputStream / BufferedOutputStream, чтобы избежать чрезмерной блокировки.

...