IO 流是 Java 基礎高頻考點,緩衝區機制是理解 IO 效能關鍵。本文針對經典面試題「什麼是緩衝區」提供標準答案與深度解析。
什麼是緩衝區?
計算機訪問外部設備或檔案,速度遠慢於直接訪問記憶體。若每次調用
read()或write()直接操作外部設備,CPU 將花費大量時間等待 I/O 響應,而非處理數據。為此,劃分一塊記憶體區域作為緩衝區。程式每次讀寫操作實際針對緩衝區進行。當緩衝區寫滿(或讀空)時,系統才集中進行一次實際的外部設備 I/O 操作。
使用記憶體緩衝區可有效提高 CPU 利用率,提升整體系統效能。
無緩衝區: 有緩衝區:
CPU → read() → 磁碟 CPU → read() → 緩衝區 (記憶體) → 滿時 → 磁碟
等待... 處理數據... 批量寫入
低效率 高效率
// 輸入緩衝
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("file.txt"));
// 內部維護 8192 字節預設緩衝區
// 輸出緩衝
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("out.txt"));
// 寫入緩衝區,滿時或 flush() 時刷入磁碟
// 按行讀取,效率極高
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
String line;
while ((line = br.readLine()) != null) { /* 處理 */ }
// 寫入緩衝
BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
bw.write("內容");
bw.newLine(); // 跨平台換行
bw.flush();
// 分配堆外記憶體,零拷貝
ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024 * 1024); // 1MB
// 適用大檔案、高併發網路傳輸
| 參數 | 預設值 | 調優建議 |
|---|---|---|
| 緩衝區大小 | 8192 bytes (8KB) | 大檔案可增至 64KB-256KB |
| 刷新策略 | 滿時自動 / 手動 flush() | 關鍵數據即時 flush() |
| 直接/堆緩衝 | 堆緩衝 | 網路/大檔案用直接緩衝 |
A:減少系統調用次數。系統調用涉及用戶態↔核心態切換、上下文切換、磁碟尋道等開銷。批量讀寫將 N 次調用合併為 1 次。
A:一次讀取大塊數據到緩衝區,在記憶體中掃描 \n,避免逐字符系統調用。
A:flush() 強制將緩衝區數據寫入目標,流保持開啟;close() 先 flush 再釋放資源關閉流。
A:直接緩衝區分配在堆外記憶體,避免 JVM GC 掃描、支援零拷貝(DMA),但分配釋放成本高、不受 -Xmx 限制但受限於 MaxDirectMemorySize。
A:關鍵數據寫入後立即 flush();使用 try-with-resources 確保 close() 執行;關鍵業務採用同步寫入 FileChannel.force(true)。
// 測試:寫入 10MB 數據
// 無緩衝:FileOutputStream 直接寫入 → ~2.5 秒
// BufferedOutputStream(8KB) → ~120 毫秒
// BufferedOutputStream(64KB) → ~80 毫秒
// FileChannel + 直接緩衝區 → ~50 毫秒
緩衝區是「以空間換時間」的經典體現。理解其原理、掌握 BufferedInputStream/OutputStream、BufferedReader/Writer、NIO ByteBuffer 三大體系用法,並根據場景調整緩衝區大小與刷新策略,是 Java 開發者處理高效 IO 的核心技能。