网络编程之Selector & SelectionKey详解(一)

来源:互联网 发布:java string contact 编辑:程序博客网 时间:2024/05/17 18:25

NIO能通过单个线程管理多个I/O通道,主要就是通过选择器Selector来实现的。

public abstract class Selector {    protected Selector() { }    public static Selector open() throws IOException {return SelectorProvider.provider().openSelector();    }    public abstract boolean isOpen();    public abstract SelectorProvider provider();    public abstract Set<SelectionKey> keys();    public abstract Set<SelectionKey> selectedKeys();    public abstract int selectNow() throws IOException;    public abstract int select(long timeout)throws IOException;    public abstract int select() throws IOException;    public abstract Selector wakeup();    public abstract void close() throws IOException;}

当我们调用

channel.register(selector, SelectionKey.OP_READ, buffer);

方法时,会将通道channel注册到选择器selector上,同时会返回一个SelectionKey选择键对象,这个键对象标识了通道和选择器之间的注册关系。选择键会记住您关心的通道。它们也会追踪对应的通道是否已经就绪。当您调用一个选择器对象的select( )方法时,相关的键建会被更新,用来检查所有被注册到该选择器的通道。您可以获取一个就绪键的集合,从而找到当时已经就绪的通道。通过遍历这些键,您可以选择出每个从上次您调用select( )开始直到现在,已经就绪的通道。

public abstract class SelectionKey {//以下四个常量是定义的通道的四种操作public static final int OP_READ = 1;public static final int OP_WRITE = 4;public static final int OP_CONNECT = 8;public static final int OP_ACCEPT = 16;//可以针对指定的通道附加一个对象 private volatile Object attachment = null;// 获得通道对象public abstract SelectableChannel channel();// 获得通道所注册的选择器public abstract Selector selector();// 验证通道和选择器之间的注册关系是否还生效public abstract boolean isValid();//将通道放入选择器的已注销集合中public abstract void cancel();//获得该通道所感兴趣的操作public abstract int interestOps();//设置通道感兴趣的操作public abstract SelectionKey interestOps(int paramInt);//获得通道已准备好的操作public abstract int readyOps();public final boolean isReadable() {return ((readyOps() & 0x1) != 0);}public final boolean isWritable() {return ((readyOps() & 0x4) != 0);}public final boolean isConnectable() {return ((readyOps() & 0x8) != 0);}public final boolean isAcceptable() {return ((readyOps() & 0x10) != 0);}public final Object attach(Object paramObject) {Object localObject = this.attachment;this.attachment = paramObject;return localObject;}public final Object attachment() {return this.attachment;}}


一个SelectionKey选择键对象包含两个以整数形式进行编码的比特掩码:一个用于指示那些通道/选择器组合体所关心的操作(instrest集合),

 另一个表示通道准备好要执行的操作(ready集合)。可以通过调用键对象的interestOps( )方法来获取,这个interset集合永远不会被选择器改变,
 但可以通过调用选择键interestOps(int value )方法并传入一个新的比特掩码参数来改变它。
 ready集合是interest集合的子集,可以通过调用键的readyOps( )方法来获取相关的通道的已经就绪的操作并且表示了interest集合中从上次调用select( )以来已经就绪的那些操作。


每个选择器selector中会包含三种键的集合,也可以认为是三种状态通道的集合,比较通道和选择键是一一对应的:

(1) 注册键的集合,通过register函数进行注册的通道这个集合可以通过Keys()方法返回

(2) 已选择键的集合,这个是注册键集合的子集,可以通过selectedKeys()方法返回,该集合中的通道都是准备好执行相应操作的通道

(3) 已取消键的集合,这个集合包含了cancel( )方法被调用过的键(这个键已经被无效化),但它们还没有被注销。这个集合是选择器对象的私有成员,因而无法直接访问。

当我们调用选择器的select()方法时,会影响上述三种键的集合,调用之后会发生如下过程:

1.已取消的键的集合将会被检查。如果它是非空的,每个已取消的键的集合中的键将从另外两个集合中移除,并且相关的通道将被注销。
这个步骤结束后,已取消的键的集合将是空的。

2.已注册的键的集合中的键的interest集合将被检查。在这个步骤中的检查执行过后,对interest集合的改动不会影响剩余的检查过程。一旦就绪条件被定下来,底层操作系统将会进行查询,以确定每个通道所关心的操作的真实就绪状态。依赖于特定的select( )方法调用,如果没有通道已经准备好,线程可能会在这时阻塞,通常会有一个超时值。直到系统调用完成为止,这个过程可能会使得调用线程睡眠一段时间,然后当前每个通道的就绪状态将确定下来。对于那些还没准备好的通道将不会执行任何的操作。对于那些操作系统指示至少已经准备好interest集合中的一种操作的通道,将执行以下两种操作中的一种:
 a.如果通道的键还没有处于已选择的键的集合中,那么键的ready集合将被清空,然后表示操作系统发现的当前通道已经准备好的操作的比特掩码将被设置。
 b.否则,也就是键在已选择的键的集合中。键的ready集合将被表示操作系统发现的当前已经准备好的操作的比特掩码更新。所有之前的已经不再是就绪状态的操作不会被清除。事实上,所有的比特位都不会被清理。由操作系统决定的ready集合是与之前的ready集合按位分离的,一旦键被放置于选择器的已选择的键的集合中,它的ready集合将是累积的。比特位只会被设置,不会被清理。


 3.步骤2可能会花费很长时间,特别是所激发的线程处于休眠状态时。与该选择器相关的键可能会同时被取消。当步骤2结束时,步骤1将重新执行,以完成任意一个在选择进行的过程中,键已经被取消的通道的注销。
 
 4.select操作返回的值是ready集合在步骤2中被修改的键的数量,而不是已选择的键的集合中的通道的总数。返回值不是已准备好的通道的总数,
 而是从上一个select( )调用之后进入就绪状态的通道的数量。之前的调用中就绪的,并且在本次调用中仍然就绪的通道不会被计入,而那些在前一次调用中已经就绪但已经不再处于就绪状态的通道也不会被计入。这些通道可能仍然在已选择的键的集合中,但不会被计入返回值中。返回值可能是0。


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 以旧换新旧的没给商家报案怎么办 宜家家居家居指南地址写错怎么办 苏宁任性付没还遭到恐吓心意怎么办 大王卡激活后一直是E网怎么办 京东退货已取走后悔了怎么办 退差价把下单立返红包退还了怎么办 苏宁电器发票丢了换电器怎么办 苹果5s访问限制密码忘了怎么办 京东买的暴风电视出现问题了怎么办 控水一个月的三角梅还没开花怎么办 帮别人办手机分期不还怎么办 国美在线没有信用卡分期不了怎么办 手机店办理分期被老板套现了怎么办 美的空调保修卡丢了怎么办 格力空调保修卡丢了怎么办 荣耀9i手机总是滑手怎么办? 春兰空调没发票不给修怎么办 洗衣机顶盖的安全开关坏了怎么办 苹果手机的开关健坏了怎么办 淘宝买的东西快递弄破损了怎么办 京东购买邮来手机里面没有怎么办 孕期建卡病历本丢了怎么办 四维检查胎儿心脏有缺陷怎么办 七个月的宝宝俩个蛋蛋都疝气怎么办 电脑有些网站看视频不能全屏怎么办 小米滑板车坏了售后不保修怎么办 红米4a电池不耐用怎么办 华为手机买个别人退货的怎么办 京东购物怎么查订单查询不到怎么办 退款了又收到货怎么办快递打电话 快递未收到货能退款商家拒绝怎么办 黑色牛仔裤有一块洗白了怎么办 黑色牛仔裤被洗衣液烧了怎么办 在蘑菇街退鞋子商家非说脏了怎么办 牛皮屑怎么办ke靠成都银康 微信订阅号取消关注之后还在怎么办 腾讯新闻红包领取说帐号异常怎么办 计算机职弥报名没选模块怎么办 有人用我手机注册有赞了怎么办 一件代发别人的货被投诉了怎么办 淘宝极速退款后商家拒收快递怎么办