Java缓冲流如何提高读写性能

本文最后更新于:3 个月前

参考:

【Java】缓冲流如何提高性能 - CSDN - 扶我起来我还要写代码(√)

0 - 前言

先说结论,使用 BufferedInputStream,BufferedOutputStream 能够提高读写性能。

传统的Java IO是基于阻塞的,他的工作状态就是“读/写,等待,读/写,等待······”。

缓冲流有字节和字符两种,原理上几乎差不读,本处以字节缓冲路来进行讨论。

1 - 缓冲输入流

1.0 - 零碎点

BufferedInputStream extends FileInputStream

缓冲流的设计思想是基于装饰器设计模式的,需要在构造缓冲流的时候传入一个节点流。 采用了缓冲技术的read(arr)方法,如果arr.length>=buf.length,那么将不会在使用buf,而是直接将磁盘上的数据填充到arr,这样才能保证最好的性能,但是可能引入的风险是arr的大小没有控制好,导致内存紧张;如果arr.length<buf.length,那么还是依旧读满整个buf,然后从buf中将数据System.arrayCopy到arr中,没有了再次读取磁盘到buf,如此重复,实际上最终和磁盘交互的并不是BufferedInputStream,而是通过构造器注入的其他节点流的native read(arr[])来实现。

1.1 - 为什么缓冲输入流能提高效率?

思想就是空间换时间的思想。一次读入足够多的数据到内存中,然后之后直接从内存中取,因此快。即牺牲部分内存空间,换快。

具体是一次读取buf个字节到内存中,默认buf是8192个字节。

调用read方法,read方法虽然是一个字节一个字节的返回数据,但是他实际上是一次就读取了buf个字节到内存中等着。

传统的IO是阻塞式的,没有采取缓冲技术,也就意味着,读取一个字节,使用IO资源,然后阻塞,然后再使用IO资源,再阻塞,直至文件读完,流关闭释放IO资源。

2 - 缓冲输出流

2.0 - 零碎点

BufferedOutputStream extends FileOutputStream。

read(int)方法的思想还是空间换时间,使用缓冲技术,则每次都是写buf,直到buf写满了才会把数据刷到磁盘。如果没有使用缓冲技术,那么每个字节都需要消耗本地的IO资源,写一个字节,使用一次IO资源,然后再阻塞再写,如此重复。

刷盘的过程是调用构造方法中传入的节点流的write(arr[])来实现的,而不是直接调用native write(int)实现。wirte(arr[])最终调用write(arr[], int, int),思想是将arr中的数据刷到磁盘。使用了缓冲流技术,如果arr.length>=buf.length,则直接将arr中的数据刷盘;如果arr.length<buf.length,则将数据写入buf,直到buf写满了才会刷盘,刷盘的过程也是调用构造方法中传入的节点流的write(arr[], int, int)完成。


Java缓冲流如何提高读写性能
https://alec-97.github.io/posts/3366410150/
作者
Shuai Zhao
发布于
2022年11月15日
许可协议