选择器
基本
- 选择器(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( ) }
- 选择器(Selector): 选择器类管理着一个被注册的通道集合的信息和他们的就绪状态.通道是和选择器一起被注册的,并且使用选择器来更新通道的就绪状态
异步关闭能力
- 任何时候都有可能关闭一个通道或者取消一个选择键,除非采取步骤进行同步,否则键的状态及相关的通道将发生意料之外的改变
多线程
- 如果想要使用更多的线程为通道提供服务,多个选择器不是好的选择,更好的策略是对所有选择通道使用一个选择器,并将对就绪通道的服务委托给其他线程
- 对于某些通道要求比其他通道更高的响应速度,可以通过使用两个选择器来解决:一个为命令链接服务,另一个为普通链接服务