как System.out.print() ведет себя в java?

Я знал, что System.out буферизуется. Он не будет печатать вывод на терминал, пока он не будет явно сброшен или программа не будет завершена.

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

Может кто подскажет причину.

class PrintandSleep {
   public static void main(String args[]) throws InterruptedException{
       System.out.print("xyz");
       Thread.sleep(5000);
   }
}

person pradeep    schedule 18.06.2014    source источник
comment
Вы, конечно, хотите поменять местами две строки?   -  person hertzsprung    schedule 18.06.2014
comment
Я действительно смущен тем, как это может сбивать с толку. Вы говорите программе печатать, а затем спать. Я не понимаю, почему вы ожидаете, что это будет по-другому. Если вы не привыкли читать снизу вверх?   -  person awksp    schedule 18.06.2014
comment
@user3580294 user3580294 Поскольку System.out должен буферизоваться строкой, OP также предполагает, что System.out.print() ничего не печатает (поскольку нигде нет новой строки), по крайней мере, пока поток не будет закрыт, в программе выход.   -  person nos    schedule 18.06.2014
comment
@nos А, это имеет смысл. Не кликал, пока ты это не сказал.   -  person awksp    schedule 18.06.2014
comment
@user3580294 user3580294 Я ожидал, что буфер будет очищен и вывод появится после завершения программы, потому что System.out является буферизованным потоком.   -  person pradeep    schedule 18.06.2014
comment
возможный дубликат Будет ли буфер Java System.out.print() навсегда до println()?   -  person Alexandre Santos    schedule 18.06.2014


Ответы (1)


Причина в том, что модуль записи построен с установленным в true флагом автоматического сброса.

public PrintStream(OutputStream out, boolean autoFlush, String encoding)

В таком случае, когда мы вызываем write(String), мы также вызываем flush().

Код из версии 8:

java.io.PrintStream

 public void print(String s) {
        if (s == null) {
            s = "null";
        }
        write(s);
    }


private void write(String s) {
        try {
            synchronized (this) {
                ensureOpen();
                textOut.write(s);
                textOut.flushBuffer();
                charOut.flushBuffer();
                if (autoFlush && (s.indexOf('\n') >= 0))
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }

Посмотрите в коде, когда вы не можете определить, что происходит.

person Damian Leszczyński - Vash    schedule 18.06.2014
comment
Интересно, что, по крайней мере, из быстрого обращения к отладчику, флаг autoFlush в данном случае фактически не имеет значения, поскольку (по крайней мере, на моем компьютере) вывод записывается в консоль до того, как флаг будет проверен. Не слишком уверен, что происходит. - person awksp; 18.06.2014
comment
Здесь мы вызываем print(String), а не write(String). В документации ничего не сказано об эффекте autoFlush. - person Joni; 18.06.2014
comment
Кроме того, интересно то, что и System.err, и System.out создаются с помощью autoFlush=true (см. hg.openjdk.java.net/jdk7/jdk7/jdk/file/cf44386c8fe3/src/share/) - не означает ли это, что выходные данные в System.err и System.out всегда должны быть синхронизированы (как мы знаем, это не так)? - person Andreas Fester; 18.06.2014
comment
@Joni, печать общедоступна, запись закрыта. Вызывая печать, вы называете запись. - person Damian Leszczyński - Vash; 18.06.2014
comment
Если это имеет значение, у меня вывод произошел при вызове charOut.flushBuffer(). Дальнейшее погружение привело к вызову класса sun.something.something, для которого у меня не было исходного кода. - person awksp; 18.06.2014
comment
@ user3580294 ... что имеет смысл, поскольку приведенный выше код показывает, что out.flush() вызывается только в том случае, если autoFlush равно true И строка содержит новую строку (которой нет в коде OP) - person Andreas Fester; 18.06.2014
comment
@Андреас Э, перепиши. Мне любопытно, как различать различные выходные потоки/писатели тогда и когда будет иметь значение сброс того или другого. Из моей проверки javadoc text/charOut.flushBuffer() просто сбрасывал некоторые буферы, не сбрасывая базовый поток байтов, поэтому мне немного любопытно, что происходит... - person awksp; 18.06.2014