NIO 之 Selector实现原理
相關文章
NIO 之 ByteBuffer實現原理
NIO 之 Channel實現原理
NIO 之 Selector實現原理
概述
Selector允許單線程處理多個 Channel。如果你的應用打開了多個連接(通道),但每個連接的流量都很低,使用Selector就會很方便。例如,在一個聊天服務器中。
這是在一個單線程中使用一個Selector處理3個Channel的圖示:
要使用Selector,得向Selector注冊Channel,然后調用它的select()方法。這個方法會一直阻塞到某個注冊的通道有事件就緒。一旦這個方法返回,線程就可以處理這些事件,事件的例子有如新連接進來,數據接收等。
Selector 作用
僅用單個線程來處理多個Channels的好處是,只需要更少的線程來處理通道。事實上,可以只用一個線程處理所有的通道。對于操作系統來說,線程之間上下文切換的開銷很大,而且每個線程都要占用系統的一些資源(如內存)。因此,使用的線程越少越好。
Selector能夠在單個線程中處理多個通道,這樣可以減少多個線程造成上下文切換問題。
Selector 源碼分析
public abstract class Selector implements Closeable {protected Selector() { }public static Selector open() throws IOException {return SelectorProvider.provider().openSelector();}public abstract boolean isOpen();public abstract SelectorProvider provider();public abstract Set<SelectionKey> keys();public abstract Set<SelectionKey> selectedKeys();public abstract int selectNow() throws IOException;public abstract int select(long timeout) throws IOException;public abstract int select() throws IOException;public abstract Selector wakeup();public abstract void close() throws IOException;Selector 是個抽象類,提供一個靜態的方法獲取Selector子類SelectorImpl的實例。
下面分析Selector的幾個方法
register 方法
該方法是在 Channel的register方法中調用的。具體詳見NIO 之 Channel實現原理
1. 通過channel和selector構造一個SelectionKey的實例。
2. SelectionKey 注冊感興趣的事件
這四種事件用SelectionKey的四個常量來表示:
SelectionKey.OP_CONNECT
SelectionKey.OP_ACCEPT
SelectionKey.OP_READ
SelectionKey.OP_WRITE
select 方法
不同的 Channel 注冊到 Selector 后,就可以隨時查詢 Selector ,找出哪些 Channel 已經準備好可以進行處理。Channel 可能準備好上面注冊到 Selector 感興趣事件中的一個或多個。
獲取就緒的 Channel,阻塞方法,沒有就緒的 Channel 就一直阻塞該線程。
獲取就緒的 Channel, 阻塞方法,阻塞 timeout 時間,如果超時還沒有就緒的 Channel,返回0,不做任何操作。
獲取就緒的 Channel,如果沒有就緒的就直接返回,不阻塞當前線程。
上面三個 select方法底層都是調用 lockAndDoSelect 方法。
lockAndDoSelect方法的參數值 說明:
-1 : 一直阻塞,直到有就緒的 Channel 可處理
0 : 不阻塞
0: 表示阻塞多長時間
keys 方法
獲取所有注冊到 Selector 上的 SelectionKeypublic Set<SelectionKey> keys() {if (!isOpen() && !Util.atBugLevel("1.4")) throw new ClosedSelectorException();return publicKeys; }selectedKeys 方法
獲取所有注冊到 Selector 上就緒 Channel 的 SelectionKey 信息。
public Set<SelectionKey> selectedKeys() {if (!isOpen() && !Util.atBugLevel("1.4")) throw new ClosedSelectorException();return publicSelectedKeys; }SelectionKey 解析
SelectionKey 類結構如下:
public abstract class SelectionKey {protected SelectionKey() { }public static final int OP_READ = 1 << 0;public static final int OP_WRITE = 1 << 2;public static final int OP_CONNECT = 1 << 3;public static final int OP_ACCEPT = 1 << 4;//附件信息private volatile Object attachment = null;.... }- public abstract SelectableChannel channel()
獲取channel對象 public abstract Selector selector()
獲取seletor對象public abstract void cancel()
從 Selector 中取消注冊該Channelpublic abstract int interestOps()
獲取該chennel 注冊到 selector 上的事件public abstract SelectionKey interestOps(int ops)
修改注冊到 selector 上的事件public abstract int readyOps()
是否讀就緒讀就緒不等于可讀,如果沒有注冊讀事件是不能讀的。
public final boolean isReadable()
判斷是否可讀public final boolean isWritable()
是否可寫public final boolean isConnectable()
是否已經連接public final Object attach(Object ob)
添加附件信息public final Object attachment()
獲取附件信息
本人簡書blog地址:http://www.jianshu.com/u/1f0067e24ff8????
點擊這里快速進入簡書
GIT地址:http://git.oschina.net/brucekankan/
點擊這里快速進入GIT
總結
以上是生活随笔為你收集整理的NIO 之 Selector实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NIO 之 Channel实现原理
- 下一篇: IO、NIO、AIO 内部原理分析