NIO的Selector

参考自

Java NIO系列教程(六) Selector

Java-NIO-Selector

java.nio.channels.Selector

NIO新功能Top 10(下) 

出发点: 如何管理多个连接?
  1. 所有连接注册到一个管理组件,当它们的状态改变(比如有数据可读、可写),就向这个管理组件发出信息。即,这个管理组件被动地监听
  2. 一个管理组件主动地一直轮询所有组件。
第一种模式很像操作系统的“中断”这种模型,可以在操作系统层面上实现。即这个管理组件可以在无事件时进入阻塞状态,当连接状态改变,它被唤醒,这时,主动方在产生事件的地方,这是一种高效的方式。
第二种模式,主动方在管理组件,由于它事先不知道连接的状态,因此这种轮询的效率很低。更会无意义地消耗CPU和IO资源。
 
读选择器建立在非阻塞模式上,所以只有通道是非阻塞模式它才会工作。如果你喜欢,还可以让实际的选择处理也变成非阻塞的。重点是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获得通道所关心的操作? 什么叫做“通道所关心的操作”?
 
 
答案:
 
1,Selector 选择器,完成主要的选择功能。select(), 并保存有注册到它上面的通道集合。  如何通过selector获得所有注册的通channel?  => Selector的keys()方法获取SelectionKey的集合,再通过SelectionKey的channel()方法获得channel
2,SelectableChannel 可被注册到Selector上的通道。  包括啥,不包括啥? 包括DatagramChannelPipe.SinkChannelPipe.SourceChannel,ServerSocketChannelSocketChannel 。不包括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己经准备好了进行哪些操作。
 
获取selectedKeys
 
使用selector.selectedKeys()
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 an UnsupportedOperationException to be thrown.
只可从中移除key,但不可以增加key。
 
在使用selector时,获取完key,并进行完操作后,需要把它从selectedKeys集合中删除。
 
SelectionKey类
 
A token representing the registration of a SelectableChannel with a Selector.
 

select方法

select()方法返回的int值表示有多少通道已经就绪。亦即,自上次调用select()方法后有多少通道变成就绪状态。
注意,是”之间“有多少通道就绪。所以可能不等于就绪的通道总数。
 但是select方法返回的集合却不只包含了两次select之间发生变化的channel,而包含了所有“准备好”的channel。这里的“准备好”是指对于那个channel注册的interest集合里的操作“准备好”。
下面是JDK里对于selection的说明

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), and selectNow() methods, and involves three steps:

  1. 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.

  2. 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:

    1. 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.

    2. 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.

  3. 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.
  4. 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实例无效。通道本身并不会关闭。

 
 
 
 
原文地址:https://www.cnblogs.com/devos/p/3749777.html