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

Java NIO 非阻塞 IO 核心原理與實戰範例

     編輯:Java 程式設計入門

從傳統 IO 到 NIO 的演進

傳統 BIO 的困境

  • 阻塞特性: read() 會一直等待資料到達,執行緒被佔用
  • 多執行緒模型: 每連線一執行緒,高併發下資源耗盡(執行緒切換開銷大、記憶體壓力)

NIO 核心架構:Reactor 模式

Java NIO 採用 Reactor(反應堆)模式,亦可視為 Observer(觀察者)模式:

  1. Selector(選擇器): 充當觀察者,監聽多個 Channel 的事件
  2. Channel(通道): 可非阻塞模式運作,註冊感興趣事件(Accept、Read、Write)
  3. SelectionKey: 代表 Channel 與 Selector 的註冊關係,攜帶事件狀態

核心流程詳解

// 1. 建立 Selector
Selector selector = Selector.open();

// 2. 建立 ServerSocketChannel 並綁定埠
ServerSocketChannel ssc = ServerSocketChannel.open();
InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 8080);
ssc.socket().bind(address);

// 3. 設定非阻塞模式
ssc.configureBlocking(false);

// 4. 向 Selector 註冊 OP_ACCEPT 事件
SelectionKey skey = ssc.register(selector, SelectionKey.OP_ACCEPT);

// 5. 事件輪詢迴圈
while (true) {
    int nKeys = selector.select(); // 阻塞直到有事件發生
    if (nKeys > 0) {
        Set selectKeys = selector.selectedKeys();
        Iterator it = selectKeys.iterator();
        while (it.hasNext()) {
            SelectionKey key = it.next();
            it.remove(); // 必須移除,避免重複處理
            
            if (key.isAcceptable()) { // 新連線事件
                ServerSocketChannel server = (ServerSocketChannel) key.channel();
                SocketChannel client = server.accept();
                client.configureBlocking(false);
                // 註冊讀寫事件
                client.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
            }
            // 處理 OP_READ、OP_WRITE 等其他事件...
        }
    }
}

關鍵點解析

  • 單執行緒處理多連線: 一個 Selector 執行緒可管理成千上萬個 Channel
  • 事件驅動: 僅在真正有資料可讀/可寫時才喚醒處理
  • Selector 底層: 作業系統級多路複用(Linux epoll、Windows IOCP、Solaris /dev/poll)

實務建議

  • 生產環境建議使用 Netty 等成熟框架,避免手寫 NIO 的坑(空輪詢 Bug、半包/黏包、記憶體洩漏)
  • 理解 SelectionKey 的附件機制(attach())可儲存上下文物件
  • 適當調整 selector.select(timeout) 避免 CPU 空轉
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved