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 。