Почему операторы System.err иногда печатаются первыми? - PullRequest
10 голосов
/ 05 февраля 2012

В Java я заметил, что иногда операторы System.err печатаются первыми перед операторами System.out, хотя последние появляются первыми перед первым в моем коде. Зачем? Мне любопытно.

Ответы [ 2 ]

17 голосов
/ 05 февраля 2012

Обычно System.out является буферизованным выходным потоком, поэтому текст накапливается до того, как он будет сброшен в место назначения. Это может значительно повысить производительность в приложениях, которые печатают большие объемы текста, поскольку сводит к минимуму количество дорогостоящих системных вызовов, которые необходимо выполнить. Однако это означает, что текст не всегда отображается сразу и может быть напечатан намного позже, чем он был написан.

System.err, с другой стороны, обычно не буферизуется, потому что сообщения об ошибках должны быть напечатаны немедленно. Это медленнее, но интуиция заключается в том, что сообщения об ошибках могут быть критичны по времени, и поэтому замедление работы программы может быть оправдано. Согласно Javadoc для System.err:

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

(Мой акцент)

Однако в результате старые данные, отправленные на System.out, могут появиться после более новых сообщений System.err, поскольку старые буферизованные данные сбрасываются позже, чем сообщение было отправлено на System.err. Например, эта последовательность событий:

  • «Привет!» Буферизируется в System.out
  • «ПАНИКА» отправляется непосредственно на System.err и печатается немедленно.
  • "Мир!" буферизируется до System.out, а буферизованные данные печатаются

Результатом будет

PANIC
Hello, world!

Даже если Hello было напечатано в System.out до того, как PANIC было напечатано в System.err.

Надеюсь, это поможет!

2 голосов
/ 05 февраля 2012

Это связано с буферизацией и приоритетом.Предположительно, Java (как и C и C-производные) не буферизует System.err, stderr и т. Д., В отличие от System.out, stdout и т. Д. Таким образом, система может гарантировать, что вы, скорее всего, получителюбые соответствующие сообщения об ошибках, даже если по той или иной причине он должен отбросить стандартный вывод.

Из Википедия :

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

...