read() 會一直等待資料到達,執行緒被佔用Java NIO 採用 Reactor(反應堆)模式,亦可視為 Observer(觀察者)模式:
// 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 等其他事件...
}
}
}
SelectionKey 的附件機制(attach())可儲存上下文物件selector.select(timeout) 避免 CPU 空轉