Java:System.out.println()背后的原因是什么?

对于可以在文本编辑器中完成的小型逻辑程序,为了跟踪我使用经典的System.out.println()

我猜你们都知道在大量迭代的块中使用它是多么令人沮丧。 为什么这么慢? 它背后的原因是什么?

这与JVM没有任何关系。 将文本打印到屏幕简单地涉及操作系统在绘制字母和尤其是滚动方面的大量工作。 如果将System.out重定向到文件,则速度会快得多。

这非常依赖于操作系统。 例如,在Windows中,写入控制台是一种阻塞操作,而且速度也很慢,因此将大量数据写入控制台会减慢(或阻止)应用程序的速度。 在unix类型的操作系统中,写入控制台是缓冲的,因此您的应用程序可以继续解锁,控制台将尽可能地赶上。

Ya,写入控制台有大量的开销。 远远大于写入文件或套接字所需的内容。 此外,如果有大量线程,他们都在同一个锁上竞争。 我建议使用其他System.out.println来跟踪。

这与Java和JVM无关,而与控制台终端无关。 在大多数操作系统中,我知道在控制台输出中写入速度很慢。

缓冲可以帮助很大。 尝试这个:

 System.setOut( new PrintStream(new BufferedOutputStream(System.out)) ); 

但要注意:你不会看到输出逐渐出现,但一切都在闪光。 哪个好,但如果你正在使用它进行调试,并且程序在终止之前崩溃,在某些情况下你可能不会在崩溃之前看到打印的文本。 这是因为在崩溃之前没有刷新缓冲区。 它被打印出来了,但是它仍然在缓冲区中,并且没有出现在你可以看到它的控制台上。 我记得在一个令人费解的调试会话中发生了这件事。 最好偶尔明确刷新,以确保您看到它:

 System.out.flush(); 

有些终端比其他终端快。 即使在一个操作系统中,这可能会有所不

这可能看起来并不直接回答你的问题,但我的建议是永远不要使用System.out进行跟踪(如果你的意思是那种调试,只是为了看看你的应用程序的进展)

System.out用于调试的问题有几个:

  • 一旦应用程序结束,当您关闭控制台时,您将松开日志

  • 一旦你的应用正常工作(或评论它们),你将不得不删除这些语句。 稍后如果你想重新激活它们,你将不得不再次取消评论/评论……乏味

我建议使用log4j并“监视”日志文件,使用tail命令 – 还有一个Tail for Windows – 或者使用像LogWatcher这样的Eclipse插件。

关于写入终端(至少在Windows中),我注意到了一件有趣的事情。 如果窗口最小化,它实际上运行得快得多。 这绝对与Michael Borgwardt关于绘图和滚动的答案密切相关。 真的,如果你的记录足够注意到减速,你可能最好写一个文件。

缓慢是由于每次换行或刷新时发生的大量Java-Native转换。 如果迭代有许多步骤,则System.out.println()没有多大帮助。 如果迭代步骤本身并不重要,则可以仅在每10或100步执行一次调用System.out.println()。 您还可以将System.out包装到BufferedOutputStream中。 当然,始终可以选择通过ExecutorService异步打印。