java selector 源码_Java-NIO Selector详解

1.Selector的作用是什么?

选择器提供选择执行已经就绪的任务的能力。从底层来看,Selector提供了询问通道是否已经准备好执行每个I/O操作的能力。「Selector 允许单线程处理多个Channel」。仅用单个线程来处理多个Channels的好处是,只需要更少的线程来处理通道。事实上,可以只用一个线程处理所有的通道,这样会大量的减少线程之间上下文切换的开销。

2.使用流程:

2.1创建

Selector selector = Selector.open();

2.2.获取通道

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

2.3.设置为非阻塞

serverSocketChannel.configureBlocking(false);

2.4.绑定连接

serverSocketChannel.bind(new InetSocketAddress(SystemConfig.SOCKET_SERVER_PORT));

2.5 将通道注册到选择器上,并制定监听事件为:“接收”事件

serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);

2.6轮询查询就绪操作

while (true) {

selector.select();

Set selectedKeys = selector.selectedKeys();

Iterator keyIterator = selectedKeys.iterator();

while(keyIterator.hasNext()) {

SelectionKey key = keyIterator.next();

if(key.isAcceptable()) {

// a connection was accepted by a ServerSocketChannel.

} else if (key.isConnectable()) {

// a connection was established with a remote server.

} else if (key.isReadable()) {

// a channel is ready for reading

} else if (key.isWritable()) {

// a channel is ready for writing

}

keyIterator.remove();

}

}

2.7select()方法详解

select()方法,可以查询出已经就绪的通道操作,这些就绪的状态集合,包存在一个元素是SelectionKey对象的Set集合中。

int select():阻塞到至少有一个通道在你注册的事件上就绪了。

int select(long timeout):和select()一样,但最长阻塞事件为timeout毫秒。

int selectNow():非阻塞,立刻返回。

select()方法返回的int值,表示有多少通道已经就绪,更准确的说,是自前一次select方法以来到这一次select方法之间的时间段上,有多少通道变成就绪状态。

3.核心类介绍

3.1 可选择通道(SelectableChannel)

判断一个Channel 能被Selector 复用,有一个前提:判断他是否继承了一个抽象类SelectableChannel。如果继承了SelectableChannel,则可以被复用,否则不能。

「SelectableChannel类是何方神圣?」

SelectableChannel类提供了实现通道的可选择性所需要的公共方法。它是所有支持就绪检查的通道类的父类。所有socket通道,都继承了SelectableChannel类都是可选择的,包括从管道(Pipe)对象的中获得的通道。而FileChannel类,没有继承SelectableChannel,因此是不是可选通道。

「通道和选择器注册之后,他们是绑定的关系吗?」

不是一对一的关系。一个通道可以被注册到多个选择器上,但对每个选择器而言只能被注册一次。

通道和选择器之间的关系,使用注册的方式完成。SelectableChannel可以被注册到Selector对象上,在注册的时候,需要指定通道的哪些操作,是Selector感兴趣的。

0c6a72964aabafb1188f27c14190ed77.png

3.2选择键(SelectionKey)

操作类型有4类:

可读 : SelectionKey.OP_READ = 1 << 0;

可写 : SelectionKey.OP_WRITE = 1 << 2;

连接 : SelectionKey.OP_CONNECT = 1 << 3;

接收 : SelectionKey.OP_ACCEPT = 1 << 4;

Channel和Selector的关系确定好后,并且一旦通道处于某种就绪的状态,就可以被选择器查询到。这个工作,使用选择器Selector的select()方法完成。select方法的作用,对感兴趣的通道操作,进行就绪状态的查询。

Selector可以不断的查询Channel中发生的操作的就绪状态。并且挑选感兴趣的操作就绪状态。一旦通道有操作的就绪状态达成,并且是Selector感兴趣的操作,就会被Selector选中,放入选择键集合中。

一个选择键,首先是包含了注册在Selector的通道操作的类型,比方说SelectionKey.OP_READ。也包含了特定的通道与特定的选择器之间的注册关系。

开发应用程序是,选择键是编程的关键。NIO的编程,就是根据对应的选择键,进行不同的业务逻辑处理。

如果Selector对通道的多操作类型感兴趣,可以用“位或”操作符来实现:int key = SelectionKey.OP_READ | SelectionKey.OP_WRITE ;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值