Java + Eclipse: синхронизация stdout и stderr - PullRequest
10 голосов
/ 24 мая 2010

Я использую Eclipse. Когда у меня есть такое заявление:

write 20 times 'Hello World\n' to stdout
write 'ERROR\n' to stderr
write 5 times 'Hello  World\n' to stdout

Вывод выглядит много раз так:

Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
...
Hello World
Hello World
Hello World
ERROR

Есть ли способ синхронизации этих двух выходных потоков? Конечно, без ожидания через несколько миллисекунд после блока 20 раз Hello World и ожидания через несколько миллисекунд после печати ERROR.

Ответы [ 5 ]

7 голосов
/ 17 ноября 2010

Верьте или нет, очистка здесь не является решением ....

Если поток приводит к "абстракции, предоставляемой базовой операционной системой" (например, дисковод или консоль), то оставшиеся байты«передаются в операционную систему для записи; это не гарантирует, что они действительно записаны ...» (см. документацию OutputStream ).Ключевым моментом здесь является то, что ОС может обрабатывать сбросы из разных потоков в разных порядках, если она того пожелает.

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

Таким образом, остается вопрос, есть ли встроенный способ синхронизации двух потоков?Или мы должны справиться с этим вручную?

6 голосов
/ 24 мая 2010

Для «серьезного» использования я предпочитаю не писать напрямую в System.out/System.err, так как он жестко кодирует место назначения, а также использует довольно странный PrintStream (это поток байтов или поток символов?),Если вы оберните выходные потоки в свой собственный PrintWriter, вы можете настроить его на автоматическую очистку - второй аргумент в конструкторе - auto-flush.

Например

PrintWriter out = new PrintWriter(System.out, true);
PrintWriter err = new PrintWriter(System.err, true);

out.println("Hello world");
//this will flush after writing the end of line

См.

2 голосов
/ 24 мая 2010

System.out и System.err являются обычными PrintStream объектами (которые предоставляют метод flush ()), поэтому попробуйте System.out.flush() и System.err.flush().

1 голос
/ 26 мая 2018

AFAIK, нет надежного способа принудительно синхронизировать 2 несвязанных потока.

Обходной путь должен использовать только один поток: например, используйте System.setErr () для перенаправления на err, чтобы все печаталось в потоке ошибок:

System.setErr(System.out);

Или наоборот через System.setOut ()

System.setOut(System.err);

Недостатком этого является то, что он может изменить подсветку синтаксиса: например, некоторые IDE могут по-разному выделять текст в stderr и stdout

0 голосов
/ 09 мая 2012

Добавьте очистку, за которой следует Thread.sleep(1), порядок вывода 99,9% будет правильным.

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

System.out.println( "stdout 1" ); System.out.flush(); Thread.sleep( 1 );
System.err.println( "stderr 1" ); System.err.flush(); Thread.sleep( 1 );
System.out.println( "stdout 2" ); System.out.flush(); Thread.sleep( 1 );
System.err.println( "stderr 2" ); System.err.flush(); Thread.sleep( 1 );

Единственный недостаток - это сон в течение 1 миллисекунды, то есть 1/1000 секунды

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