【Netty】NIO 选择器 ( Selector ) 简介
文章目錄
- I . 選擇器 ( Selector )
- II . 選擇器 ( Selector ) 與 NIO 特性
- III . 選擇器 ( Selector ) API 簡介
- IV . SelectionKey 簡介
- V . 選擇器 ( Selector ) 工作流程
I . 選擇器 ( Selector )
NIO ( 非阻塞 IO ) 使用單個線程管理多個 通道 ( Channel ) 就是通過 選擇器 ( Selector ) 實現(xiàn)的 ;
選擇器 ( Selector ) 簡介 :
① 注冊機制 : 選擇器 ( Selector ) 可以注冊多個 通道 ( Channel ) , 注冊過程是以事件的方式進行注冊 , 如果有事件觸發(fā) , 那么 選擇器 ( Selector ) 就會針對該事件類型進行對應(yīng)處理 ;
② 注冊后的操作 : 通道 注冊給 選擇器 之后 , 每個線程對應(yīng)的 選擇器 ( Selector ) 才能監(jiān)控客戶端向服務(wù)器中對應(yīng)的 通道 ( Channel ) 寫出的數(shù)據(jù) ;
③ 輪詢機制 : 選擇器 ( Selector ) 工作時 , 不停地在輪詢其所注冊的 通道 ( Channel ) , 處理該 通道 所注冊的對應(yīng)事件 ;
④ 非阻塞機制 : 只有 客戶端連接 有數(shù)據(jù)寫入時 , 才會觸發(fā)事件 , 線程才開始處理該客戶端對應(yīng)的操作 , 如果沒有數(shù)據(jù)寫入 , 線程也不會在此阻塞 , 轉(zhuǎn)而處理其它事務(wù) ;
II . 選擇器 ( Selector ) 與 NIO 特性
選擇器 ( Selector ) 與 NIO 特性 :
① 多路復(fù)用 : 選擇器 ( Selector ) 又稱為 多路復(fù)用器 , 為服務(wù)器的一個線程管理多個客戶端連接 ;
② 輪詢機制 : 客戶端通過 Socket 向服務(wù)器發(fā)送數(shù)據(jù) , 被 選擇器 ( Selector ) 輪詢到 , 線程就會開始為該客戶端服務(wù) ;
③ 單線程多個連接 : 如果 該客戶端 沒有發(fā)送數(shù)據(jù) , 線程不會在此阻塞 , 線程會為其它的客戶端服務(wù) , 因此一個線程可以管理與多個客戶端的連接 ;
④ 非阻塞 : 服務(wù)器端 的線程 不會因為客戶端沒有發(fā)送數(shù)據(jù)而阻塞 , 因此稱為 非阻塞 IO , 該機制提升了線程的 IO 效率 ;
⑤ 優(yōu)點 : 服務(wù)器端單個線程可以非阻塞地并發(fā)處理與多個客戶端連接的讀寫操作 , 提高了系統(tǒng)的 可伸縮性 , 性能 ;
III . 選擇器 ( Selector ) API 簡介
選擇器 ( Selector ) 是 NIO 中的三大核心組件之一 ;
下面是 Selector API 相關(guān)簡介 ;
1 . Selector 抽象類 說明 : Selector 是一個抽象類 , 其中定義了 打開 , 關(guān)閉 , 選擇 , 鍵集 ( SelectionKey ) 相關(guān)的方法 ;
public abstract class Selector2 . 打開 關(guān)閉 選擇器 ( Selector ) 相關(guān)方法 :
① Selector open() 方法 : 打開選擇器 , 作用是獲取一個選擇器 ;
② boolean isOpen() 方法 : 判定選擇器是否已經(jīng)打開 ;
③ void close() 方法 : 關(guān)閉選擇器 ;
3 . 選擇 相關(guān)方法 : 監(jiān)聽通道事件 , 如果有事件發(fā)生 , 返回發(fā)生的事件個數(shù) ;
① int select(long timeout) 方法 : 開始監(jiān)控該 選擇器 ( Selector ) 所注冊的 通道 ( Channel ) , 如果某個 通道中有 IO 操作觸發(fā) , 將 通道 ( Channel ) 對應(yīng)的 選擇鍵 ( SelectionKey ) 加入到其待處理集合中 ;
- long timeout 參數(shù) : 設(shè)置的超時時間 ;
② int select() 方法 : 監(jiān)聽通道事件 , 如果有事件發(fā)生 , 返回發(fā)生的事件個數(shù) , 如果沒有事件發(fā)生會一直保持阻塞 ;
③ int selectNow() 方法 : 監(jiān)聽通道事件 , 如果有事件發(fā)生 , 返回發(fā)生的事件個數(shù) , 如果沒有事件發(fā)生 , 返回 0 ;
4 . 選擇操作的阻塞說明 :
① 阻塞 : 選擇器 ( Selector ) 的 select() 方法執(zhí)行的是 阻塞 操作 , 直到其所關(guān)聯(lián)的 通道 ( Channel ) 有一個有事件發(fā)生 ;
② 帶超時的阻塞 : 選擇器 ( Selector ) 的 select(long timeout) 方法 是阻塞 操作 , 但是如果 timeout 毫秒內(nèi)沒有事件發(fā)生 , 就解除阻塞 ;
③ 非阻塞 : 選擇器 ( Selector ) 的 selectNow() 方法是 非阻塞的操作 , 如果當(dāng)前沒有事件發(fā)生 , 立刻返回 , 有事件發(fā)生將 SelectionKey 放入集合再返回 , 總之不阻塞 ;
5 . 阻塞 喚醒相關(guān)方法 :
Selector wakeup() 方法 : 如果 選擇器 ( Selector ) 調(diào)用了 select() 方法 或 select(long timeout) 方法 , 當(dāng)前處于阻塞狀態(tài) , 那么就會立刻解除阻塞 ;
6 . 鍵集 相關(guān)方法 :
① Set<SelectionKey> selectedKeys() 方法 : 獲取 選擇器 ( Selector ) 所有有事件發(fā)生的通道的 SelectionKey 集合 , 上面的 select() 方法只能選擇一個 ;
② Set<SelectionKey> keys() 方法 : 獲取 選擇器 ( Selector ) 所注冊的有的通道的 SelectionKey ;
IV . SelectionKey 簡介
SelectionKey 簡介 :
① SelectionKey 作用 : SelectorImpl 是 Selector 的實現(xiàn)類 , 在其中可以看到很多 SelectionKey 的 Set 集合 ;
② SelectionKey 集合 : 存儲有事件發(fā)生的 通道 ( Channel ) 對應(yīng)的 SelectionKey ;
public abstract class SelectorImpl extends AbstractSelector {protected Set<SelectionKey> selectedKeys = new HashSet();protected HashSet<SelectionKey> keys = new HashSet();private Set<SelectionKey> publicKeys;private Set<SelectionKey> publicSelectedKeys;... }③ 通道 注冊給 選擇器 : 通道 ( Channel ) 注冊到 選擇器 ( Selector ) 中 , 每個 通道 ( Channel ) 都有一個對應(yīng)的 SelectionKey ;
④ 事件觸發(fā)機制 : 選擇器 ( Selector ) 監(jiān)控到某通道有事件發(fā)生 , 就會拿到該通道對應(yīng)發(fā)生的事件的 個數(shù) , 之后處理事件時 , 再去遍歷 SelectionKey 集合 , 通過 SelectionKey 可以獲取對應(yīng)的 通道 ( Channel ) , 線程開始為該 通道 ( Channel ) 進行服務(wù) ;
⑤ 通過 SelectionKey 獲取 通道 ( Channel ) : 在 SelectionKey 中定義了獲取 通道 的方法 , 可以直接獲取對應(yīng)的通道 ;
public abstract SelectableChannel channel()⑥ 獲取觸發(fā)事件的通道 : 調(diào)用 選擇器 ( Selector ) 的 select() 方法 , 就可以獲得有幾個 通道 ( Channel ) 中有事件發(fā)生 , 將有事件發(fā)生的 通道 的 SelectionKey 放入到集合中 ;
⑦ 觸發(fā)的事件 : 上述集合中每個 SelectionKey 都代表一個對應(yīng) 通道 ( Channel ) 的事件 , 如 : 客戶端 TCP 連接 , 讀取數(shù)據(jù) , 寫出數(shù)據(jù) 等事件 ;
V . 選擇器 ( Selector ) 工作流程
1 . 創(chuàng)建通道 : 服務(wù)器端 , 每當(dāng)有客戶端連接服務(wù)器時 , 服務(wù)器的 ServerSocketChannel 就會創(chuàng)建一個與客戶端對應(yīng)的 SocketChannel ;
2 . 注冊通道 : 將創(chuàng)建的 SocketChannel 注冊給 選擇器 ( Selector ) , 調(diào)用通道的 register() 方法將 通道 ( Channel ) 注冊給選擇器 ( Selector ) ;
① 注冊對應(yīng)關(guān)系 : 一個 選擇器 ( Selector ) 可以注冊多個 通道 ( Channel ) ;
② 注冊返回值 : 通道 注冊給 選擇器 后 , 會返回 SelectionKey , 此時將 SelectionKey 放入 選擇器 ( Selector ) 的集合中進行管理 , 調(diào)用 選擇器的 keys() 方法 , 可以獲取這些注冊的 SelectionKey 的 Set 集合 ;
③ 常用的注冊方法 : ops 指的是關(guān)注的事件 ;
SelectionKey register(Selector sel, int ops) SelectionKey register(Selector sel, int ops, Object att)3 . 選擇器 ( Selector ) 開始監(jiān)聽 : 調(diào)用 select() , select(long timeout) , selectNow() 方法 , 以 阻塞或非阻塞 的方式獲取其管理的通道中 , 有幾個通道觸發(fā)了事件 ;
事件的種類 :
- OP_READ : 讀取數(shù)據(jù)事件 ;
- OP_WRITE : 寫出數(shù)據(jù)事件 ;
- OP_CONNECT : 連接操作事件 ;
- OP_ACCEPT : 等待連接操作事件 ;
4 . 獲取 SelectionKey : 獲取有事件發(fā)生的 通道 ( Channel ) 的 SelectionKey ;
5 . 獲取 SelectionKey 對應(yīng)的通道 : 調(diào)用 SelectionKey 的 channel() 方法 , 可以獲取 SelectionKey 對應(yīng)的 通道 ( Channel ) ;
6 . 通道 ( Channel ) 處理 : 執(zhí)行真正的業(yè)務(wù)處理流程 ;
總結(jié)
以上是生活随笔為你收集整理的【Netty】NIO 选择器 ( Selector ) 简介的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Netty】NIO 缓冲区 ( Buf
- 下一篇: 【Netty】NIO 选择器 ( Sel