NIO-选择器


选择器

  1. 基本

    • 选择器(Selector): 选择器类管理着一个被注册的通道集合的信息和他们的就绪状态.通道是和选择器一起被注册的,并且使用选择器来更新通道的就绪状态
      //选择器维护了一个需要监控的通道集合,一个给定的通道可以被注册到多个选择器上
      //选择器对象是线程安全的
      public abstract class Selector {
        //打开选择器
        public static Selector open( ) throws IOException
        //选择器是否打开
        public abstract boolean isOpen( );
        //关闭选择器
        public abstract void close( ) throws IOException;
        //返回创建此通道的提供程序
        public abstract SelectionProvider provider( );
        //阻塞: 选择一组其相应通道准备好进行的I/O操作的键
        public abstract int select( ) throws IOException;
        //阻塞:
        public abstract int select (long timeout) throws IOException;
        //非阻塞: 立即返回
        public abstract int selectNow( ) throws IOException;
        //结束阻塞的select方法立即返回
        public abstract void wakeup( );
        //返回此选择器的键集
        public abstract Set keys( );
        //返回此选择器的选择键集,需要从键集手动移除(键集不是线程安全的)
        public abstract Set selectedKeys( );
      }
    • 可选择通道(SelectableChannel): 这个抽象类提供了实现通道的可选择性所需要的公共方法,它是所有支持就绪检查的通道类的父类.FileChannel对象不是可选择的(没有继承),所有socket通道都是可选择的,包括从管道(Pipe)对象中获得的通道.SelectableChannel可以被注册到Selector对象上,同时可以指定选择器的操作,一个通道可以被注册到多个选择器上,但对每个选择器而言只能被注册一次.
      public abstract class SelectableChannel extends AbstractChannel implements Channel {
        //部分API列表
        //将通道注册到给定选择器上,并规定操作,返回一个选择键(必须为非阻塞通道,同时一旦被注册,就不能回到阻塞状态)
        public abstract SelectionKey register (Selector sel, int ops) throws ClosedChannelException;
        //att设置附加对象到选择键中
        public abstract SelectionKey register (Selector sel, int ops,Object att) throws ClosedChannelException;
        //检查通道是否已经被注册到选择器上
        public abstract boolean isRegistered( );
        //返回与该通道指定的选择键
        public abstract SelectionKey keyFor (Selector sel);
        //获取通道所支持的操作集合
        public abstract int validOps( );
        //在通道被注册到一个选择器上时必须先设置通道为非阻塞模式: configureBlocking(false)
        public abstract void configureBlocking (boolean block) throws IOException;
        //是否为阻塞模式
        public abstract boolean isBlocking( );
        //获取阻塞模式的锁对象
        public abstract Object blockingLock( );
      }
    • 选择键(SelectionKey): 选择键封装了特定的通道与特定的选择器的注册关系.选择键对象被SelectableChannle.register()返回并提供一个表示这种注册关系的标记.选择键包含了两个比特集(以整数的形式进行编码),指示了该注册关系所关心的通道操作,以及通道已经准备好的操作
      public abstract class SelectionKey {
        public static final int OP_READ     //读操作
        public static final int OP_WRITE    //写操作
        public static final int OP_CONNECT  //连接操作,Client端支持的一种操作
        public static final int OP_ACCEPT   //连接可接受操作,仅ServerSocketChannel支持
        //返回此选择键所关联的通道
        public abstract SelectableChannel channel( );
        //返回此选择键所关联的选择器
        public abstract Selector selector( );
        //取消选择键注册,取消的键不会立即从selector中移除,而是添加到cancelledKeys中
        //在下一次select操作中移除它,所以在调用某个选择键时需要使用isValid校验
        public abstract void cancel( );
        //检查此选择键是否有效
        public abstract boolean isValid( );
        //获得此选择键的感兴趣操作集
        public abstract int interestOps( );
        public abstract void interestOps (int ops);
        //获取此选择键的准备好的操作集
        public abstract int readyOps( );
        //检测此选择键是否可读操作
        public final boolean isReadable( )
        //检测此选择键是否可写操作
        public final boolean isWritable( )
        //检测此选择键关联的通道是否完成套接字连接操作
        public final boolean isConnectable( )
        //检测此选择键关联的通道是否已经准备好接受新的套接字链接操作
        public final boolean isAcceptable( )
        //将给定附件对象注册到此选择键上
        public final Object attach (Object ob)
        //获取此选择键上注册的附件对象
        public final Object attachment( )
      }
  2. 异步关闭能力

    • 任何时候都有可能关闭一个通道或者取消一个选择键,除非采取步骤进行同步,否则键的状态及相关的通道将发生意料之外的改变
  3. 多线程

    • 如果想要使用更多的线程为通道提供服务,多个选择器不是好的选择,更好的策略是对所有选择通道使用一个选择器,并将对就绪通道的服务委托给其他线程
    • 对于某些通道要求比其他通道更高的响应速度,可以通过使用两个选择器来解决:一个为命令链接服务,另一个为普通链接服务

文章作者: Bryson
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Bryson !
评论
 上一篇
下一篇 
NIO-通道 NIO-通道
通道基础 基本 顶层的Channel接口,只有两个操作: 检查一个通道是否打开(isOpen())和关闭一个打开的通道(close())public interface Channel{ public boolean isOpen()
2019-09-12
  目录