控制台输出是阻塞操作吗?

时间:2013-06-25 17:41:56

标签: java multithreading scala blocking nonblocking

当Java程序调用System.out.println()或Scala程序调用println()时,线程阻塞吗?

我正在编写一个包含大量子任务的Scala程序。每个子任务都在Future中执行。建议actor和future内的代码不会阻塞,以便后续任务也不必等待。但我想在控制台上打印很多。

如果是阻止操作:我可以做些什么来优化性能?

  • 我应该使用专用线程进行控制台输出,以便该线程是唯一可以阻塞的线程吗?
  • 还有其他任何建议吗?

当然,我可以尝试减少输出量或在StringBuilder中收集一些输出并一起打印,这样可以减少输出操作的数量。

2 个答案:

答案 0 :(得分:13)

  

当Java程序调用System.out.println()或Scala程序调用println()时,线程阻塞吗?

是和否。 System.outPrintStream,是同步类。因此,将大量写入System.out的多个线程肯定会相互阻塞。然而,一旦线程获得锁定,IO是否将阻止线程取决于体系结构。如果您编写的大量IO超出底层硬件的容量,那么写阻塞。此外,制作大量小写(与缓冲相反)也会使线程变慢。

  

我是否应该使用专用线程进行控制台输出,以便线程是唯一可以阻塞的线程?

很棒的主意,是的。然后,这个线程可以通过单个BufferedWriter或某种log4j或其他日志包来编写,与System.out相比,它会更高效。您将需要使用BlockingQueue之类的内容来排队同步的消息,但IO永远不会阻止此队列,除非您生成的消息比IO通道可以持续生成的消息更快。

  

当然,我可以尝试减少输出量或在StringBuilder中收集一些输出并一起打印,这样可以减少输出操作的数量。

BufferedWriter将为您解决此问题。

  

还有其他任何建议吗?

  • 如上所述,使用更好的日志包或单线程编写器。
  • 将日志写入具有更多IO带宽的其他物理磁盘。
  • 切换到内存文件系统或硬件以增加IO带宽。 SSD ++。
  • 通过网络将其发送到另一个盒子,以执行实际的持续关闭框。
  • 使用GzipOutputStream动态压缩它。

答案 1 :(得分:4)

取决于。在 Windows 操作系统上,它是一个阻塞操作,涉及很多内核,可以将某些东西打印到控制台。在 UNIX -like OS中,操作被缓冲,因此不会感觉很慢。

我建议你使用缓冲区方法,并且有一个单独的线程也是一个好主意。或者如果您的输出不那么重要,您可以将其写入文件,这比写入控制台要快得多。