缓冲区是一块特定的内存区域。开辟缓冲区的目的是通过缓解应用程序上下层之间的性能差异,提高系统性能。
缓冲可以协调上层组件和下层组件的性能差异。当上层组件性能由于下层组件时,可以有效地减少上层组件对下层组件的等待时间。例如,在操作系统中,为了改善 CPU 与 I/O 设备速度不匹配的矛盾,设置了缓冲区,程序输出的数据先送到缓冲区暂存,然后由I/O 设备慢慢地处理。这时,CPU不必等待,可以继续执行程序。实现了CPU与I/O设备之间的并行工作。事实上,凡在数据的到达速率与其离去速率不同的地方,都可设置缓冲,以缓和它们之间速度不匹配的矛盾。
缓冲最常用的场景就是提高 I/O 速度。为此 JDK 内不少 I/O 组件都提供了缓冲功能。比如,使用 FileWriter时,进行文件写操作的代码如下:
public class BufferTest { public static final int CIRCLE = 100000; public static void test1() throws Exception { Writer writer = new FileWriter(new File("file1.txt")); for (int i = 0; i < CIRCLE; i++) { writer.write(i); } writer.close(); } public static void test2() throws Exception { Writer writer = new BufferedWriter( new FileWriter(new File("file2.txt"))); for (int i = 0; i < CIRCLE; i++) { writer.write(i); } writer.close(); } public static void main(String[] args) throws Exception { test1(); test2(); } }
test1() 使用普通的 FileWriter 类进行写文件,而 test2() 使用 BufferedWriter 为 FileWriter 对象增加了缓存功能。
BufferedWriter 有两个构造函数:
public BufferedWriter(Writer out) public BufferedWriter(Writer out, int sz)
第一个构造函数将构造大小为 8K 的缓冲区。一般来说,缓冲区不宜过小,过小的缓冲区无法企到真正的缓冲作用,缓冲区也不易过大,过大的缓冲区会浪费系统内存,增加 GC 负担。
第二个构造函数允许手动指定缓冲区大小。
分别运行两个方法,使用 TPTP 分析运行时间:
可以观察到,使用了缓冲区和未使用缓冲区的写文件花费的时间相差有 3~5 倍之多。
另一个有用的缓冲组件是 BufferedOutputStream。使用 它可以包装所有的 OutputStream , 为其提供缓冲功能,提高输出流的效率。和BufferedWriter 类似,它也提供了两个构造函数
public BufferedOutputStream(OutputStream out) public BufferedOutputStream(OutputStream out, int size)
作用类似于上文提到的 BufferedWriter 。
除了能够改善 I/O 性能,缓冲区对任何一种上下层组件存在性能差异的场合都可以得到很好的效果。例如绘图类程序,可以使用内存缓冲区,先在内存中画图,然后一次性显示出整个图像。
除了性能上的优化,缓冲区还可以作为上层组件和下层组件的一种通信工具。从而将上层和下层组件解耦,优化设计结构。例如使用生产者消费者模式,连接生产者和消费者的缓冲区。