跳至主要內容

NIO:选择器

mozzie大约 2 分钟JavaJava

NIO:选择器

基本介绍

选择器(Selector) 是 SelectableChannle 对象的多路复用器,Selector 可以同时监控多个通道的状况,利用 Selector 可使一个单独的线程管理多个 Channel,Selector 是非阻塞 IO 的核心

  • Selector 能够检测多个注册的通道上是否有事件发生(多个 Channel 以事件的方式可以注册到同一个 Selector),如果有事件发生,就获取事件然后针对每个事件进行相应的处理,就可以只用一个单线程去管理多个通道,也就是管理多个连接和请求
  • 只有在连接/通道真正有读写事件发生时,才会进行读写,就大大地减少了系统开销,并且不必为每个连接都创建一个线程,不用去维护多个线程
  • 避免了多线程之间的上下文切换导致的开销

常用API

创建 Selector:Selector selector = Selector.open();

向选择器注册通道:SelectableChannel.register(Selector sel, int ops, Object att)

  • 参数一:选择器,指定当前 Channel 注册到的选择器

  • 参数二:选择器对通道的监听事件,监听的事件类型用四个常量表示

  • 读 : SelectionKey.OP_READ (1)

  • 写 : SelectionKey.OP_WRITE (4)

  • 连接 : SelectionKey.OP_CONNECT (8)

  • 接收 : SelectionKey.OP_ACCEPT (16)

  • 若不止监听一个事件,使用位或操作符连接:int interest = SelectionKey.OP_READ | SelectionKey.OP_WRITE

  • 参数三:可以关联一个附件,可以是任何对象

Selector API

方法说明
public static Selector open()打开选择器
public abstract void close()关闭此选择器
public abstract int select()阻塞选择一组通道准备好进行 I/O 操作的键
public abstract int select(long timeout)阻塞等待 timeout 毫秒
public abstract int selectNow()获取一下,不阻塞,立刻返回
public abstract Selector wakeup()唤醒正在阻塞的 selector
public abstract Set selectedKeys()返回此选择器的选择键集

SelectionKey API:

方法说明
public abstract void cancel()取消该键的通道与其选择器的注册
public abstract SelectableChannel channel()返回创建此键的通道,该方法在取消键之后仍将返回通道
public final Object attachment()返回当前 key 关联的附件
public final boolean isAcceptable()检测此密钥的通道是否已准备好接受新的套接字连接
public final boolean isConnectable()检测此密钥的通道是否已完成或未完成其套接字连接操作
public final boolean isReadable()检测此密钥的频道是否可以阅读
public final boolean isWritable()检测此密钥的通道是否准备好进行写入

基本步骤:

//1.获取通道
ServerSocketChannel ssChannel = ServerSocketChannel.open();
//2.切换非阻塞模式
ssChannel.configureBlocking(false);
//3.绑定连接
ssChannel.bin(new InetSocketAddress(9999));
//4.获取选择器
Selector selector = Selector.open();
//5.将通道注册到选择器上,并且指定“监听接收事件”
ssChannel.register(selector, SelectionKey.OP_ACCEPT);
贡献者: mozzie