我正在向标准输出中写入大量数据,并指出根据输出控制台,程序执行时间是可变的。例如,在NetBeans控制台上,该程序比在Windows cmd中要慢。
因此,我认为写入stdout会填充一个缓冲区,并且当该缓冲区已满时(控制台输出消耗的速度不够快),写入就会变得阻塞。
我用Java程序重现了这种行为。
这里有一个输出数据的程序。
public class Output {
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10_000; i++) {
System.out.println("Awesone Output ");
}
System.out.println("Total time : " + (System.currentTimeMillis() - start));
}
}
这里是一个使用上述程序中的数据的程序
public class StdoutBlocking {
public static void main(String[] args) throws IOException, InterruptedException {
ProcessBuilder processBuilder = new ProcessBuilder("java", "stackoverflowDemo.StdoutBlocking.Output");
processBuilder.directory(new File("C:/Users/me/Documents/NetBeansProjects/tmp/build/classes"));
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
String lastLine = null;
while ((line = reader.readLine()) != null) {
Thread.sleep(10);
lastLine = line;
}
System.out.println("done : " + lastLine);
}
}
我启动第二个开始输出并使用其输出的输出。 没有睡眠,输出程序确实非常快,而且非常慢。
那么这个缓冲区的大小是多少?
这只是出于我的好奇心,我并不想实现某些特殊目的
答案 0 :(得分:2)
System.out
和System.err
的默认缓冲区大小为8192。您可以通过查看println(String)
之类的方法的源代码来查看它。他们使用BufferedWriter
作为默认缓冲区大小。
答案 1 :(得分:1)
Without sleep the program is really quick with it's very slow.
与缓冲区大小无关。您的程序每行输出(10000行)至少睡眠10毫秒。因此,使用Thread.sleep(10)
,您的程序至少要100秒钟不执行任何操作。这就是使用Thread.sleep()
时速度较慢的原因。
关于System.out.println()
的性能,请检查以下问题:Why is System.out.println so slow?
底层操作系统操作(在控制台窗口上显示字符)很慢,因为
1。字节必须发送到控制台应用程序(应该非常快)
2。每个字符都必须使用(通常)真字体显示(这很慢,关闭抗锯齿可以提高性能,顺便说一句)
3。可能需要滚动显示区域才能在可见区域中添加新行(最好的情况:位块传输操作,最坏的情况:重新渲染整个文本区域)
您还可以在Javadoc中的Process
类中找到它
由于某些本机平台仅为标准输入和输出流提供了有限的缓冲区大小,因此未能及时写入子流程的输入流或读取子流程的输出流可能导致子流程阻塞甚至死锁。
对于UNIX,您可以检查以下链接:https://unix.stackexchange.com/questions/11946/how-big-is-the-pipe-buffer