为什么有时会先打印System.err语句?

时间:2012-02-05 01:50:44

标签: java stdout stderr

在Java中,我注意到有时候,System.err语句会先在System.out语句之前打印,尽管后者在我的代码中首先出现在前者之前。为什么?我很好奇。

2 个答案:

答案 0 :(得分:17)

通常,System.out是缓冲的输出流,因此在将文本刷新到目标位置之前会累积文本。这可以显着提高打印大量文本的应用程序的性能,因为它可以最大限度地减少必须进行的昂贵系统调用的次数。但是,这意味着文本并不总是立即显示,并且打印时间可能比写入的时间晚得多。

另一方面,

System.err通常不会被缓冲,因为错误消息需要立即打印。这是较慢的,但直觉是错误消息可能是时间关键的,因此程序减速可能是合理的。根据{{​​3}}:

  

通常,此流对应于主机环境或用户指定的显示输出或其他输出目标。 按照惯例,此输出流用于显示错误消息或应立即引起用户注意的其他信息,即使主要输出流(变量out的值)已重定向到通常不会持续监控的文件或其他目的地。

(我的重点)

但是,因此,发送到System.out的旧数据可能会在较新的System.err消息之后显示,因为旧的缓冲数据会在消息发送到System.err之后刷新。例如,这一系列事件:

  • “你好”,缓冲到System.out
  • “PANIC”会直接发送至System.err并立即打印。
  • “世界!”被缓冲到System.out,并打印缓冲的数据

会导致输出

PANIC
Hello, world!

即使在Hello打印到System.out之前,PANIC已打印到System.err

希望这有帮助!

答案 1 :(得分:2)

它与缓冲和优先级有关。据推测,Java(如C和C衍生物)不会缓冲System.errstderr等,与System.outstdout等不同。这样,系统可以确保您最有可能获得任何相关的错误消息,即使由于某种原因必须丢弃标准输出。

来自Wikipedia

  

将标准输出和标准错误定向到同一目的地(例如文本终端)是可接受的 - 也是正常的。除非涉及缓冲,否则消息的显示顺序与程序写入的顺序相同。 (例如,常见的情况是标准错误流是无缓冲的,但标准输出流是行缓冲的;在这种情况下,如果标准输出流的缓冲区不是,则稍后写入标准错误的文本可能会更早出现在终端上但已经满了。)