在java 8中,在以下几个方面是否有真正的区别:
try (OutputStream os = Files.newOutputStream(path)) {
[...]
}和
try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(path))) {
[...]
}我读过这个所以问题和答案,但它让我很困惑。
PS: Java 11中有什么变化吗?
发布于 2019-04-27 22:44:47
不同的是,当一个未缓冲的系统每次给它一个字节来写时,它对底层系统进行写调用,而缓冲输出流则是将要写入的数据存储在一个缓冲区中,使系统调用只在调用flush命令之后才写数据。这是通过减少调用的I/O操作来提高性能。
https://docs.oracle.com/javase/8/docs/api/java/io/BufferedOutputStream.html https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html
发布于 2019-04-29 07:18:26
正如在这个答案中所解释的,缓冲流应该减少系统调用的数量。只有当应用程序发出大量小的读或写请求,导致大量系统调用时,这才是相关的。这就是链接答案所说的“低效”的含义。
通过使用大得多的缓冲区(可以使用单个调用来读取或写入缓冲区),并通过从缓冲区复制或复制到缓冲区来满足应用程序请求,您将减少系统调用的数量。如果保存的系统调用比引入的复制开销更昂贵,这将提高性能。
所以,使用缓冲流并不总是更好的原因,因为并不是每个应用程序都发出如此小的请求。当应用程序发出合理大小的请求时,缓冲流所能做的最好的事情就是退出,因此如果它有一个空缓冲区,并且应用程序发出的请求大小与缓冲区的大小相同甚至更大,则缓冲流将直接将请求传递给源流。
但是,如果应用程序的缓冲区稍微少一点,则缓冲流将完成其缓冲工作,从而引入额外的复制开销。但是如前所述,如果您确实保存了系统调用,并且根据体系结构的不同,您可能只能说,“…”如果您实际上保存了大量的系统调用“。更大的缓冲区本身并不是一种改进。
一个简单的例子是,比如说,您只想将1000个字节写到一个文件中,例如
byte[] data = /* something producing an array of 1,000 bytes */
try (OutputStream os = Files.newOutputStream(path)) {
os.write(data);
}因此,如果将输出流包装在一个BufferedOutputStream中,您将得到一个默认大小为8192字节的缓冲区。由于这个缓冲流不知道要写多少内容,所以它会将请求数据复制到它的缓冲区,因为它比较小,在关闭操作期间将被刷新(写)。因此,最终,您不会保存任何系统调用,而是获得复制开销。
因此,缓冲流并不总是更有效;在某些情况下,缓冲甚至会降低性能。此外,有时应用程序不感兴趣的是最高性能,而是对及时写入底层媒体感兴趣。如果流已经是一个OutputStream,那么包装一个BufferedOutputStream、在需要时获得缓冲要比选择退出缓冲要容易。
当您查看JDK1.4中引入的NIO通道API时,您会注意到没有缓冲通道。相反,它不提供读取或写入单个字节的方法,而且,它迫使程序员使用ByteBuffer来指导他们分离I/O和数据处理。这是最好的方法。
https://stackoverflow.com/questions/55885443
复制相似问题