缓冲流通过内存缓冲区将多次小i/o合并为一次大i/o,大幅减少系统调用次数;默认8kb缓冲区可使10kb读取从10240次系统调用降至2次,本质是以内存空间换时间;缓冲区大小需依场景调整,过大浪费内存,过小削弱优化效果。

缓冲流通过在内存中开辟一块临时区域(缓冲区),把多次零散的读写操作“攒起来”,统一和磁盘打交道,从而大幅减少系统调用次数——这才是性能提升的核心逻辑。
缓冲区怎么减少系统调用?
磁盘 I/O 远比内存操作慢得多。比如读取 10KB 数据:
- 非缓冲流:每次 read() 读 1 字节,触发 10240 次系统调用,频繁陷入内核、切换上下文
- 缓冲流(默认 8KB 缓冲区):第一次 read() 就从磁盘批量加载 8KB 到内存;后续 8192 次读操作全在内存完成,只触发 2 次系统调用(一次读前 8KB,一次读后 2KB)
本质是用「内存空间」换「系统调用时间」,I/O 次数下降几个数量级,耗时自然锐减。
缓冲区如何实际参与读写?
它不是被动容器,而有明确的填充与消费机制:
- 读过程:BufferedInputStream 的 read() 先查内部缓冲区;若空或不够,才调用底层 FileInputStream.fill() 一次性读满缓冲区(如 8KB),再返回所需字节
- 写过程:BufferedOutputStream 的 write() 先存入缓冲区;等缓冲区满、调用 flush() 或 close() 时,才把整块数据交给 FileOutputStream 写入磁盘
- 所有中间操作都绕过磁盘,只在 JVM 堆内存里流转,速度接近数组访问
缓冲区大小怎么影响性能?
不是越大越好,要匹配使用场景:
- 顺序读大文件(如日志归档):可设 32KB–64KB,降低 fill() 频次,提升吞吐
- 小文件或随机读(如配置文件加载):保持默认 8KB 即可,设太小反而增加填充次数
- 内存紧张环境(如嵌入式 Java):避免超过 128KB,缓冲区全占堆内存,可能触发 GC
- 不建议低于 1KB:起不到明显合并效果,还白占对象开销
别忘了 flush 和 close 的时机
写入的数据不会立刻落盘:
- 没 flush() 也没 close() → 数据卡在缓冲区,目标文件可能为空或截断
- close() 会自动 flush(),所以 try-with-resources 是最安全写法
- 需要实时可见(如审计日志),就在关键点手动 bos.flush()
这步漏掉,性能再高也白搭——文件内容不完整,等于没写。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











