参考自
- 所有连接注册到一个管理组件,当它们的状态改变(比如有数据可读、可写),就向这个管理组件发出信息。即,这个管理组件被动地监听
- 一个管理组件主动地一直轮询所有组件。
读选择器建立在非阻塞模式上,所以只有通道是非阻塞模式它才会工作。如果你喜欢,还可以让实际的选择处理也变成非阻塞的。重点是Selector对象会帮助你卖力地检查大量通道的状态,你只需要操作选择的结果而不用亲自去管理每一个通道。
Selector 的出现,大大改善了多个 Java Socket的效率。在没有NIO的时候,轮询多个socket是通过read阻塞来完成,即使是非阻塞模式,我们在轮询socket是否就绪的时候依然需要使用系统调用。而Selector的出现,把就绪选择交给了操作系统(我们熟知的selec函数),把就绪判断和读取数据分开,不仅性能上大有改善,而且使得代码上更加清晰。
Java NIO的选择器部分,实际上有三个重要的类。
1,Selector 选择器,完成主要的选择功能。select(), 并保存有注册到他上面的通道集合。 如何通过selector获得所有注册的通channel?
2,SelectableChannel 可被注册到Selector上的通道。 包括啥,不包括啥?
3,SelectionKey 描述一个Selector和SelectableChannel的关系。并保存有通道所关心的操作。 怎么通过SelectionKey获得通道所关心的操作? 什么叫做“通道所关心的操作”?
2,SelectableChannel 可被注册到Selector上的通道。 包括啥,不包括啥? 包括DatagramChannel, Pipe.SinkChannel, Pipe.SourceChannel,ServerSocketChannel, SocketChannel 。不包括FileChannel
3,SelectionKey 描述一个Selector和SelectableChannel的关系。并保存有通道所关心的操作。 怎么通过SelectionKey获得通道所关心的操作? 什么叫做“通道所关心的操作”? SelectionKey的interestOps()返回interest set,这是一个int值。
The interest set determines which operation categories will be tested for readiness the next time one of the selector's selection methods is invoked. The interest set is initialized with the value given when the key is created; it may later be changed via the
interestOps(int)
method.- 即,这个channel会被检测发生了什么事件。比如成功建立连接,可以接受新连接,可读,可写
- SelectionKey.OP_CONNECT 当一个socket channel成功连接到另一个服务器时,称为“连接就续”, 通过isConnectable()判断。
- SelectionKey.OP_ACCEPT 当一个server socket channel准备好接收新进入的连接,称为“连接就绪”。isAcceptable()
- SelectionKey.OP_READ 当一个channel有数据可读时,称为“读就绪”. isReadable()
- SelectionKey.OP_WRITE 当一个channel等待被写入时,称为"写就绪". isWritable()
即interest set用来在select过程中用来测试一个channel己经准备好了进行哪些操作。
public abstract Set<SelectionKey> selectedKeys()
Keys may be removed from, but not directly added to, the selected-key set. Any attempt to add an object to the key set will cause anUnsupportedOperationException
to be thrown.
SelectableChannel
with a Selector
.select方法
select()方法返回的int值表示有多少通道已经就绪。亦即,自上次调用select()方法后有多少通道变成就绪状态。注意,是”之间“有多少通道就绪。所以可能不等于就绪的通道总数。
Selection
During each selection operation, keys may be added to and removed from a selector's selected-key set and may be removed from its key and cancelled-key sets. Selection is performed by the
select()
,select(long)
, andselectNow()
methods, and involves three steps:
Each key in the cancelled-key set is removed from each key set of which it is a member, and its channel is deregistered. This step leaves the cancelled-key set empty.
The underlying operating system is queried for an update as to the readiness of each remaining channel to perform any of the operations identified by its key's interest set as of the moment that the selection operation began. For a channel that is ready for at least one such operation, one of the following two actions is performed:
If the channel's key is not already in the selected-key set then it is added to that set and its ready-operation set is modified to identify exactly those operations for which the channel is now reported to be ready. Any readiness information previously recorded in the ready set is discarded.
Otherwise the channel's key is already in the selected-key set, so its ready-operation set is modified to identify any new operations for which the channel is reported to be ready. Any readiness information previously recorded in the ready set is preserved; in other words, the ready set returned by the underlying system is bitwise-disjoined into the key's current ready set.
If all of the keys in the key set at the start of this step have empty interest sets then neither the selected-key set nor any of the keys' ready-operation sets will be updated.
If any keys were added to the cancelled-key set while step (2) was in progress then they are processed as in step (1).
Whether or not a selection operation blocks to wait for one or more channels to become ready, and if so for how long, is the only essential difference between the three selection methods.
close()
用完Selector后调用其close()方法会关闭该Selector,且使注册到该Selector上的所有SelectionKey实例无效。通道本身并不会关闭。