8.JAVA NIO核心之选择器(Selector)


highlight: arduino-light

选择器(Selector)概述

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

image.png

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

1.ServerSocketChannel会和Selector绑定

2.所有的SocketChannel请求连接ServerSocketChannel上,表明自己监听事件类型。

3.Selector会监听SocketChannel,返回一个 SelectionKey, 会和该Selector 关联(集合)

4.当有事件发生时,可以遍历所有的SelectKey,判断是否是对应的监听事件类型

在通过 SelectionKey 反向获取 SocketChannel , 方法 channel()

5.如果是 那么就做处理。

isAcceptable() isReadable() isWritable()

以服务端A,客户端B、C为例,

1.A绑定一个Selector,并启动

2.B请求A,A注册事件到Selector(即接收、读、写),加入到SelectKeys

3.C请求A,A注册事件到Selector(即接收、读、写),加入到SelectKeys

4.服务端A空转判断是否有事件发生,如果有事件发生

while (selector.select() > 0){

//从SelectKeys获取所有的SelectKey

//判断SelectKey事件类型

//做对应处理即可

}

如果B注册了读,那么B向A发送数据会触发selector.select() > 0的判断,并且B对应的SelectKey的isReadable是true

Selector相关API

Selector 类是一个抽象类, 常用方法和说明如下:

java public abstract class Selector implements Closeable { //得到一个选择器对象,真实类型是WindowSelectorImpl,不同操作系统selector类型不一样 public static Selector open(); public int select(long timeout);//监控所有注册的通道,返回有事件发生的通道的个数.当其中有 IO 操作可以进行时,将对应的 SelectionKey 加入到内部集合中并返回,参数用来设置超时时间 ​ public int select();//相当于select(0)返回有事件发生的通道的个数.当其中有 IO 操作可以进行时,将对应的 SelectionKey 加入到内部集合中并返回 ​ public Set<SelectionKey> keys();//从内部集合中得到所有的 SelectionKey     public Set<SelectionKey> selectedKeys();//有事件发生的 SelectionKey }

SelectionKey常量

表示 Selector 和网络通道的注册关系, 共四种:

int OP_ACCEPT:有新的网络连接可以 accept,值为 16

int OP_CONNECT:代表连接已经建立,值为 8

int OP_READ:代表读操作,值为 1

int OP_WRITE:代表写操作,值为 4

源码中:

public static final int OP_READ = 1 << 0;

public static final int OP_WRITE = 1 << 2;

public static final int OP_CONNECT = 1 << 3;

public static final int OP_ACCEPT = 1 << 4;

SelectionKey方法

java public abstract class SelectionKey {     public abstract Selector selector();//得到与之关联的 Selector 对象     public abstract SelectableChannel channel();//得到与之关联的通道     public final Object attachment();//得到与之关联的共享数据     public abstract SelectionKey interestOps(int ops);//设置或改变监听事件     public final boolean isAcceptable();//是否可以 accept     public final boolean isReadable();//是否可以读     public final boolean isWritable();//是否可以写 }

Selector流程说明

java 对下图的说明: 当客户端连接时,会通过ServerSocketChannel 得到 SocketChannel Selector通过select 方法进行监听,返回有事件发生的通道的个数. ​ 将socketChannel注册到Selector上, register(Selector sel, int ops), 一个selector上可以注册多个SocketChannel ​ 注册后返回一个 SelectionKey, 会和该Selector 关联(集合) 进一步得到各个 SelectionKey (有事件发生) 在通过 SelectionKey 反向获取 SocketChannel ,通过channel()方法 得到的 channel , 完成业务处理

选择器(Selector)的应用

java //1. 获取通道 ServerSocketChannel ssChannel = ServerSocketChannel.open(); //2. 切换非阻塞模式 ssChannel.configureBlocking(false); //3. 绑定连接 ssChannel.bind(new InetSocketAddress(9898)); //4. 获取选择器 Selector selector = Selector.open(); //5. 将通道注册到选择器上, 并且指定“监听接收事件” ssChannel.register(selector, SelectionKey.OP_READ); //监听多个时间 //ssChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);

当调用 register(Selector sel, int ops) 将通道注册选择器时,选择器对通道的监听事件,需要通过第二个参数 ops 指定。可以监听的事件类型(用 可使用 SelectionKey 的四个常量 表示):

  • 读 : SelectionKey.OP_READ (1)
  • 写 : SelectionKey.OP_WRITE (4)
  • 连接 : SelectionKey.OP_CONNECT (8)客户端监听
  • 接收 : SelectionKey.OP_ACCEPT (16)
  • 若注册时不止监听一个事件,则可以使用“位或”操作符连接。
  • 若想修改监听事件:例如修改为写事件调用selectionKey.interestOps(SelectionKey.OP_WRITE )

java int interestSet = SelectionKey.OP_READ|SelectionKey.OP_WRITE

  • OP_READ 数据已经筹备好了,能够读了,也成为了读就绪。
  • OP_WRITE 已经能够通过通道向缓冲区中写数据了,也称为写就绪。
  • OP_CONNECT 连接已就绪
  • OP_ACCEPT 服务端曾经监听到了客户端发动的连接申请,能够与服务端建立连接的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值