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