В Java я заметил, что иногда инструкции System.err
печатаются сначала перед операторами System.out
, хотя последний появляется первым перед первым в моем коде. Зачем? Мне любопытно.
Почему операторы System.err сначала печатаются?
Ответ 1
Как правило, System.out
представляет собой буферный выходной поток, поэтому текст накапливается до того, как он будет сброшен в место назначения. Это может значительно повысить производительность приложений, которые печатают большие объемы текста, поскольку это минимизирует количество дорогостоящих системных вызовов, которые необходимо выполнить. Однако это означает, что текст не всегда отображается сразу и может быть распечатан намного позже, чем он был написан.
System.err
, с другой стороны, обычно не буферизируется, потому что сообщения об ошибках должны немедленно печататься. Это медленнее, но интуиция заключается в том, что сообщения об ошибках могут быть критичными по времени, и поэтому замедление программы может быть оправдано. Согласно Javadoc для System.err
:
Обычно этот поток соответствует отображению вывода или другому выходному целевому адресу, указанному средой или пользователем хоста. По соглашению, этот выходной поток используется для отображения сообщений об ошибках или другой информации, которая должна сразу обращать внимание пользователя, даже если основной выходной поток, значение переменной out, был перенаправлен на файл или другой пункт назначения, который обычно не контролируется постоянно.
(Мой акцент)
Однако в результате старые данные, отправленные на System.out
, могут отображаться после более новых сообщений System.err
, поскольку старые буферизованные данные очищаются позже, чем сообщение было отправлено на System.err
. Например, эта последовательность событий:
- "Привет," буферизуется до
System.out
- "PANIC" отправляется непосредственно на
System.err
и печатается немедленно. - "мир!" буферизуется до
System.out
, и буферизованные данные печатаются
Результатом будет вывод
PANIC
Hello, world!
Даже если Hello
был напечатан до System.out
, прежде чем PANIC
был напечатан на System.err
.
Надеюсь, это поможет!
Ответ 2
Это связано с буферизацией и приоритетом. Предположительно, Java (например, C и C-производные) не буферизует System.err
, stderr
и т.д., В отличие от System.out
, stdout
и т.д. Таким образом, система может гарантировать, что вы, скорее всего, получите любые соответствующие сообщения об ошибках, даже если он должен отказаться от стандартного вывода по той или иной причине.
Из Wikipedia:
Допустимо - и нормальное - для стандартного вывода и стандартной ошибки должно быть направлено в тот же пункт назначения, как текстовый терминал. Сообщения отображаются в том же порядке, в каком программа записывает их, если не используется буферизация. (Например, обычная ситуация заключается в том, что стандартный поток ошибок небуферизирован, но стандартный выходной поток буферизируется по строке, в этом случае текст, записанный на стандартную ошибку позже, может появляться на терминале раньше, если стандартный буфер потока вывода не является но полный.)