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

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

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

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

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

(我的重点)

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

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

会导致输出

 PANIC Hello, world! 

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

希望这可以帮助!

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

来自维基百科 :

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