首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 非同步 IO (NIO.2) 完整指南:AsynchronousFileChannel 兩種操作模式實戰

     編輯:Java 相關知識

非同步 IO 核心類別

Java 7 引入 NIO.2,提供真正的非同步 IO 能力,核心通道類別:

  • AsynchronousFileChannel:檔案非同步讀寫
  • AsynchronousSocketChannel:客戶端非同步 Socket
  • AsynchronousServerSocketChannel:伺服器端非同步接受連線

兩種完成通知模式

模式介面特點適用場景
Future 模式Future<V>主動輪詢/阻塞等待結果需同步等待結果、可中斷、可超時控制
Callback 模式CompletionHandler<V,A>完成時自動回調高併發、不想阻塞執行緒、事件驅動架構

Future 模式實作:大檔案非同步讀取

try (AsynchronousFileChannel channel = 
        AsynchronousFileChannel.open(Paths.get("large-file.dat"))) {
    
    ByteBuffer buffer = ByteBuffer.allocateDirect(100 * 1024 * 1024); // 100MB 直接記憶體
    Future<Integer> result = channel.read(buffer, 0); // 位置 0 開始讀
    
    // 執行其他有用工作
    while (!result.isDone()) {
        System.out.println("讀取中,可處理其他任務...");
        // doOtherWork();
    }
    
    System.out.println("實際讀取位元組數: " + result.get()); // 阻塞直到完成
} catch (IOException | InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

Callback 模式實作:非同步寫入

byte[] data = {2, 3, 5, 7, 11, 13, 17, 19, 23};
ByteBuffer buffer = ByteBuffer.wrap(data);

CompletionHandler<Integer, Object> handler = new CompletionHandler<Integer, Object>() {
    @Override
    public void completed(Integer result, Object attachment) {
        System.out.println("寫入完成,位元組數: " + result);
        // 可在此鏈接下一個非同步操作
    }
    
    @Override
    public void failed(Throwable exc, Object attachment) {
        System.err.println("寫入失敗: " + exc.getMessage());
    }
};

try (AsynchronousFileChannel channel = AsynchronousFileChannel.open(
        Paths.get("primes.txt"), 
        StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
    
    channel.write(buffer, 0, null, handler); // attachment 可傳遞上下文物件
    
    // 主執行緒需等待,否則程式結束通道關閉
    Thread.sleep(10000); 
} catch (IOException | InterruptedException e) {
    e.printStackTrace();
}

執行緒池與資源管理

  • 預設使用 JVM 共享執行緒池(ForkJoinPool.commonPool())
  • 可自訂執行緒池:AsynchronousFileChannel.open(path, executor)
  • try-with-resources 確保通道關閉,但需注意:關閉通道會取消未完成操作

CompletionHandler 進階方法

方法用途
completed(result, attachment)成功回調
failed(exc, attachment)失敗回調
awaitUninterruptibly()阻塞等待且不可中斷
awaitUntil(Date deadline)限時等待

對比:非同步 vs 多路複用

  • 非同步 IO (AIO):核心完成 IO 後通知應用,適用於高併發、長耗時操作
  • 多路複用 (NIO):Selector 輪詢通道就緒狀態,單執行緒管理多連線,適用於大量短連線
  • Java 兩者共存,可根據業務特性混合使用

實務建議

  1. 大檔案順序讀寫:Files.copy() 或 FileChannel.transferTo() 零拷貝更高效
  2. 網路服務:Netty 等框架封裝了 NIO/AIO,生產環境優先使用成熟框架
  3. 直接記憶體 (allocateDirect) 減少堆外拷貝,但分配/回收成本較高,需池化
  4. 錯誤處理:ExecutionException 包裝真實異常,需 getCause() 獲取
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved