依《Unix 網路編程》:阻塞 IO、非阻塞 IO、IO 多路複用、信號驅動 IO、異步 IO。POSIX 標準僅分同步 IO(實際讀寫阻塞請求線程)與異步 IO(OS 完成讀寫後通知結果)。Java NIO 2.0 引入異步 IO(AIO),含檔案與網路兩大類。
| 類/介面 | 角色 |
|---|---|
| AsynchronousChannel | 標記支援異步操作的 Channel |
| AsynchronousServerSocketChannel | TCP Server 端,綁定/監聽/接受連線 |
| AsynchronousSocketChannel | TCP 連線通道,異步讀寫 |
| AsynchronousChannelGroup | Channel 群組,綁定線程池共享資源,扮演 Proactor 角色 |
| CompletionHandler<V,A> | 異步操作完成回調:completed/failed/cancelled |
AsynchronousChannelGroup 即 Proactor 實現,三種建立方式:
withFixedThreadPool(nThreads, factory)
withCachedThreadPool(executor, initialSize)
withThreadPool(executor)
AsynchronousChannelGroup(綁定快取線程池)。AsynchronousServerSocketChannel.open(group) 開啟伺服器通道。SO_REUSEADDR、SO_RCVBUF。bind(new InetSocketAddress("localhost",8080), 100) 綁定端口,backlog=100。accept(null, AcceptHandler) 等待連線。public void completed(AsynchronousSocketChannel ch, Object att) {
configureChannel(ch); // 設定 TCP_NODELAY 等
AioSession session = new AioTCPSession(config, readBufferSize, timeout);
session.start(); // 內部發起 pendingRead()
registerSession(session);
pendingAccept(); // 關鍵:遞歸發起下一次 accept
}
注意:回調執行於群組線程池,嚴禁阻塞/長耗時操作,否則耗盡線程池導致系統卡死。
pendingRead():channel.read(buffer, this, readHandler)。completed(bytesRead):bytesRead < 0 表示對端關閉 → 關閉連線;>0 翻轉 buffer → decode() 解碼訊息 → compact() → 再次 pendingRead()。pendingWrite(msg):channel.write(buffer, this, writeHandler)。completed(bytesWritten):檢查 buffer 是否剩餘,無剩餘則從隊列移除並觸發 onMessageSent;若隊列仍有訊息 → 繼續 pendingWrite。ByteBuffer,避免頻繁分配。程式碼片段來源於 yanf4j AIO 分支:SVN 地址。