方法 | 用途 |
---|---|
select() | 选择一组键,此方法执行处于阻塞模式的选择操作。仅在至少选择一个通道、调用此选择器的 wakeup 方法、当前的线程已中断,或者给定的超时期满(以先到者为准)后此方法才返回。 |
selectNow() | 选择一组键,此方法执行非阻塞的选择操作。如果自从前一次选择操作后,没有通道变成可选择的,则此方法直接返回零,相当于select(0L) |
select(long timeout) | 选择一组键,其相应的通道已为 I/O 操作准备就绪。 |
keys() | 返回此选择器的键集。 |
selectedKeys() | 返回此选择器的已选择键集。 |
【整理自jdk1.7】
选择器
选择器中维护了三个键集(键值对,可选择通道到选择器的注册)
- 键集:所有注册到此选择器的通道都保存在此集合中
- 已选择键集:即前一次选择操作到本次选择期间,检测每个键的通道是否已经至少为该键的相关操作集所标识的一个操作准备就绪(即监听每一个通道的所有操作标识中,只要有一个是准备就绪状态,就把它添加到此集合中)。已选择键集始终是键集的一个子集
- 已取消键集:是已被取消但其通道尚未注销的键的集合。不可直接访问此集合。已取消键集始终是键集的一个子集。
通过关闭某个键的通道或者是调用该键的 cancel 方法来取消键,取消的键将被添加到已取消键集中。已取消键集中的键,在下一次“选择”(select())操作期间将注销该键的通道,而在注销时将从所有选择器的键集(键集、已选择键集、已取消键集)中移除该键。
选择
在每次选择操作期间,都可以将键添加到选择器的已选择键集以及从中将其移除,并且可以从其键集和已取消键集中将其移除。选择是由 select()、select(long) 和 selectNow() 方法执行的,执行涉及三个步骤:
- 将已取消键集中的每个键从所有键集中移除(如果该键是键集的成员),并注销其通道。此步骤使已取消键集成为空集。
- 在开始进行选择操作时,应查询基础操作系统来更新每个剩余通道的准备就绪信息,以执行由其键的相关集合所标识的任意操作。对于已为至少一个这样的操作准备就绪的通道,执行以下两种操作之一:
- 如果该通道的键尚未在已选择键集中,则将其添加到该集合中,并修改其准备就绪操作集,以准确地标识那些通道现在已报告为之准备就绪的操作。丢弃准备就绪操作集中以前记录的所有准备就绪信息。
- 如果该通道的键已经在已选择键集中,则修改其准备就绪操作集,以准确地标识所有通道已报告为之准备就绪的新操作。保留准备就绪操作集以前记录的所有准备就绪信息;换句话说,基础系统所返回的准备就绪操作集是和该键的当前准备就绪操作集按位分开 (bitwise-disjoined) 的。
如果在此步骤开始时键集中的所有键都有空的相关集合,则不会更新已选择键集和任意键的准备就绪操作集。
- 如果在步骤 (2) 的执行过程中要将任意键添加到已取消键集中,则处理过程如步骤
是否阻塞选择操作以等待一个或多个通道准备就绪,如果这样做的话,要等待多久,这是三种选择方法之间的唯一本质差别。
并发性
选择器自身可由多个并发线程安全使用,但是其键集并非如此。
选择操作在选择器本身上、在键集上和在已选择键集上是同步的,顺序也与此顺序相同。在执行上面的步骤 (1) 和 (3) 时,它们在已取消键集上也是同步的。
一般情况下,选择器的键和已选择键集由多个并发线程使用是不安全的。如果这样的线程可以直接修改这些键集之一,那么应该通过对该键集本身进行同步来控制访问。这些键集的 iterator 方法所返回的迭代器是快速失败 的:如果在创建迭代器后以任何方式(调用迭代器自身的 remove 方法除外)修改键集,则会抛出 ConcurrentModificationException。
部分源码
- 类继承实现结构
一般带Windows或者 win的基本都与系统有关,不同的系统有不同的实现,其核心实现思想在SelectorImpl中
protected HashSet keys;//“键集” 与选择器关联的key集合
protected Set selectedKeys;//“已选择键集”就绪key集合,即已经操作事件准备就绪的选择key
private Set publicKeys;//外部访问key集合的代理
private Set publicSelectedKeys;//外部访问就绪key集合代理
private Set<SelectionKey> cancelledKeys ;已取消键集
引:http://www.importnew.com/26258.html
也就是注册的键集都保存在 keys中,必须经过select 方法才能进入到selectedKeys中,所以处理完的selectedKeys中的key,要从selectedKeys中删除