selector
對象能夠經過調用Selector.open()來建立,這個工廠方法會使用系統默認的selector provider來建立一個新的selector對象。或者咱們還能夠經過實現抽象類SelectorProvider
自定義一個selector provider,調用new SelectorProviderImpl().openSelector()來建立它。selector
將會一直保持打開狀態
。SelectionKey key = channel.register(selector,Selectionkey.XXX);
複製代碼
channel
的register方法,將channel
註冊到給定的selector
中,並返回一個表示註冊關係的SelectionKey 對象。一個selector
維護着三個selection keys集合:html
key set 包含着全部selectionKey
s,當前全部註冊到selector
中的channel
返回的註冊關係SelectionKey都包含在內,這個集合能夠經過selector.keys() 方法返回。java
selected-key set 包含着一部分selectionKey
s,其中的每一個selectionKey
所關聯的channel
在selection operation
期間被檢測出至少 準備好
了一個能夠在興趣集
中匹配到的操做。這個集合能夠經過調用selector.selectedKeys()方法返回。selected-key set 必定是 key set 的子集。api
cancelled-key set 也包含着一部分selectionKey
s,其中的每一個selectionKey
都已經被取消
,可是所關聯channel
尚未被撤銷登記
。cancelled-key set 不可以被直接返回,但也必定是 key set 的子集。安全
對於一個新建立的selector
其中這三個集合都是空着的。多線程
經過channel
的register方法,一個selectionKey
被增長到selector
的 key set 中。併發
不管經過channel.close()仍是經過selectionKey.cancel()來取消
一個selectionKey
,這個selectionKey
都會被當即添加到selector
的 cancelled-key set 中,可是所關聯的channel
並無當即被撤銷登記
,直到發生下次 selection operations
, 這些channel
才被從selector
中撤銷登記
,與此同時這些Cancelled keys纔會被從這個selector
的全部selectionKey set
(多是_key set_、selected-key set、cancelled-key set)中移除,可是不會影響這些集合自己。oracle
在 selection operations
期間,一些selectionKey
會被選中添加到 selected-key set 中。其中的每一個key
能夠經過selectiedKeys.remove()或selectiedKeys.iterator().remove()直接從 selected-key set 中移除,除此以外不可以經過任何方式被直接移除。特殊的,selected-key set 中的keys
還能夠在 selection operations
期間被間接移除。可是是不能夠直接向 selected-key set 添加key
的。ide
selection operation
期間, keys均可以從selector's selected-key set 被添加或者移除,同時也能夠從它的 key 和 cancelled-key sets 被移除。 selection operation
能夠被觸發經過執行selector.select(),selector.select(long),和selector.selectNow() 方法,而且這些方法涉及到如下三個步驟:
首先每一個位於 cancelled-key set 中的
key
會從每一個包含它的key
集合中被移除,而且對應的channel
會被撤銷登記
。這個步驟使得 cancelled-key set 變爲空。spa查詢底層操做系統來得到關於
selector
中剩餘channel
的就續事件
從selection operation
開始截止到此刻的更新狀況,只要哪一個channel
的就續事件的更新部分
有至少一個與興趣集
中的操做匹配上,那麼將會執行如下兩個動做:操作系統
若是這個
channel's key
沒有存在
於 selected-key set 那麼將它添加到這個集合中,並將它的就緒操做集
(ready-operation set)修改爲只包含
使得channel
被報告就緒的操做,任何先前記錄在就緒操做集
中的就緒信息都會被丟棄。不然,若是這個
channel's key
存在
於 selected-key set ,那麼就保留就緒操做集
中先前的就緒信息,並將這些 使得channel
被報告就緒的操做 寫入進去;總而言之,系統底層會經過按位與&操做
更新當前就緒集。若是這些
Key
的興趣集
爲空,那麼 selected-key set 和 keys'的就續集
(ready-operation sets)都不會被更新。若是在步驟(2)正在進行時將任何
key
添加到 cancelled-key set,則按步驟(1)處理它們。
selection operations
是否會阻塞等待一個或多個通道準備就緒,以及等待多長時間,這是三種選擇方法之間惟一的本質區別。多線程併發狀況下Selectors
自己是線程安全的,可是他們所持有的key sets
不是線程安全的。
selection operations
按順序在selector
自己,key set 和 selected-key set 上同步。 它們還在上面的步驟(1)和(3)期間在 canceled-key set 上同步。
在 selection operations
期間改變key
的興趣集
,對於本次操做將不會產生任何影響;它們的影響將會再下次 selection operations
期間發生。
selectionKey
可能會被取消,channel
可能隨時關閉。 所以,在一個或多個選擇器的key集
中存在並不意味着selectionKey
有效或其channel
是開放的。有可能另外一個線程取消selectionKey
或關閉一個channel
,應用程序代碼應該當心地同步並檢查這些條件。
一個線程經過selector.select()或selector.select(long)方法產生的阻塞能夠被其餘線程用如下三種方式的任意一種來中斷:
By invoking the selector's wakeup() method,
By invoking the selector's close() method, or
By invoking the blocked thread's interrupt() method, in which case its interrupt status will be set and the selector's wakeup() method will be invoked.
selector.close() 在 selection operations
期間會順序的同步selector
and all three key sets
。
一個selector
的 key set 和 selected-key set 一般狀況下是線程不安全的。若是一個線程想要修改這個集合,須要同步控制它。經過key集合
的iterator()方法返回的Iterators
提供了快速失敗
(fail-fast):若是在建立迭代器以後修改了set,除了經過調用迭代器本身的remove() 方法以外,將拋出ConcurrentModificationException 。