java NIO --selector
傳統的IO 編程中,針對每一個客戶端連接都會創建一個新的線程;
而 NIO 一個線程可以處理很多客戶端的請求
我們分析源碼的註解,可以歸納出:
1. Selector 構造方式:(常見的Seletor 構造方式)
源碼:
* <p> A selector may be created by invoking the {@link #open open} method of
* this class, which will use the system‘s default {@link
* java.nio.channels.spi.SelectorProvider selector provider} to
* create a new selector. A selector may also be created by invoking the
* {@link java.nio.channels.spi.SelectorProvider#openSelector openSelector}
* method of a custom selector provider. A selector remains open until it is
* closed via its {@link #close close} method.
翻譯:
Selector 是通過調用這個類的open()方法進行創建的,它使用的是系統默認的 選擇器提供者去創建一個新的Selector;
也可以調用spi 裏的 openSelector 方法進行自定義Selector 的創建;
在調用close 方法之前,Selector 是保持打開的;
結果:
Selector selector = Selector.open(); //Selector 構造方式
2. 關於通道的註冊以及selector 管理通道發生的事件(selector 是通過事件進行監聽的)
源碼:
* <p> A key is added to a selector‘s key set as a side effect of registering a * channel via the channel‘s {@link SelectableChannel#register(Selector,int) * register} method. Cancelled keys are removed from the key set during * selection operations. The key set itself is not directly modifiable.
翻譯解析:
我們可以通提供過繼承了SelectableChannel 的類的 register 方法進行通道的註冊,返回SelectionKey 在註冊的同時,一個key 也會加入到選擇器的鍵集裏;
需要註意的是 只有繼承了 SelectableChannel 的類 才能夠進行註冊;
在註冊方法中有兩個參數 SelectionKey register(Selector sel, int ops) ;Selector 就是我們的選擇器, ops 是我們需要監聽的事件,
以socketChannel 為例:
//創建Selector 選擇器對象
Selector selector = Selector.open();
//創建ServerSocketChannel
ServerSocketChannel socketChannel = ServerSocketChannel.open();
//設置非阻塞模式
socketChannel.configureBlocking(false);
//創建ServerSocket 綁定端口
ServerSocket socket=socketChannel.socket();
socket.bind(new InetSocketAddress(9999));
//進行通道的註冊
socketChannel.register(selector, SelectionKey.OP_ACCEPT);
3.. SelectionKey : SelectionKey 是 java NIO 中重要的值(我們可以認為是通道註冊的唯一值):
源碼:
* <p> A selectable channel‘s registration with a selector is represented by a * {@link SelectionKey} object. A selector maintains three sets of selection * keys:
翻譯:
selector 選擇器中可選擇的通道註冊是由 SelectionKey 這個對象表示的,也就是說,在Selector 註冊的不同通道,都會有一個 SelectionKey 對應;,這個
SelectionKey 是可以追溯的,也可以通過 SelectionKey 來獲取當前 SelectionKey 的通道channel;
一個選擇器裏維護了三種選擇集 分別是如下:
源碼:
* <li><p> The <i>key set</i> contains the keys representing the current
* channel registrations of this selector. This set is returned by the
* {@link #keys() keys} method. </p></li>
*
* <li><p> The <i>selected-key set</i> is the set of keys such that each
* key‘s channel was detected to be ready for at least one of the operations
* identified in the key‘s interest set during a prior selection operation.
* This set is returned by the {@link #selectedKeys() selectedKeys} method.
* The selected-key set is always a subset of the key set. </p></li>
*
* <li><p> The <i>cancelled-key</i> set is the set of keys that have been
* cancelled but whose channels have not yet been deregistered. This set is
* not directly accessible. The cancelled-key set is always a subset of the
* key set. </p></li>
翻譯理解:
1. 鍵集:包含了選擇器裏當前通道註冊的鍵,可以通過keys 方法進行返回這個鍵集;它是最全所有的鍵集
2.selected 鍵集 : 一句話就是當前selector 監聽的事件觸發返回的一個鍵集合, 可以通過selectKeys()方法進行獲取;它是鍵集(1)的子類
3. cancelled 鍵集:是一個被取消的鍵集,但是通道還沒有被撤銷登記,這幾集合不能直接被操作,也是鍵集(1)的子類
java NIO --selector