JAVA NIO系列(四) 选择器
前面介绍过Channel、Buffer,后面的文章主要讲解Selector的实践以及实现原理,选择器的概念比起通道、缓冲区要复杂一些,并且选择器是NIO中最重要的一部分内容。
为什么使用Selector
Selector又称为“选择器”,单个线程通过Selector可以管理多个SelectableChannel,实际应用中管理多个请求连接。对于操作系统来说,线程之间上下文切换的开销很大,而且每个线程都要占用系统的一些资源,比如内存,因此使用的线程越少越好。

一、Selector的创建
Selector s = Selector.open();
二、通道注册
channel.configureBlocking(false);
SelectionKey key = channel.register(s, SelectionKey.OP_ACCEPT);
Channel与Selector配合使用,必须将通道注册到选择器上,通过调用SelectableChannel的register()方法。注册完成之后,会返回此通道向选择器注册的键。
注册的时候调用的是SelectableChannel,所以注册仅支持父类是SelectableChannel的通道类;另外通道要设置成非阻塞模式,所以FileChannel不能与Selector一起使用(因为FileChannel不能切换到非 阻塞模式),而socket通道可以
register(Selector sel,int ops)方法调用的是SelectableChannel的注册方法,其中第二个参数是一个interest集合,表示在通过Selector监听Channel时对什么事件感兴趣。事件分为以下四种:
1、Connect
2、Accept
3、Read
4、Write
通道触发了一个事件意思是该事件已经就绪:
1、某个channel成功连接到另一个服务器称为“连接就绪”;
2、一个server socket channel准备好接收新进入的连接称为“接收就绪”
3、一个有数据可读的通道可以说是“读就绪”
4、等待写数据的通道可以说是“写就绪”
三、SelectionKey
表示 SelectableChannel 在 Selector 中的注册的标记,每次向选择器注册通道时就会创建一个选择键。选择键中包含的内容有:
1、interset集合
2、ready集合
3、Channel
4、Selector
一旦向Selector注册了一个或多个通道,就可以调用几个重载的select()方法,这些方法返回你所感兴趣的事件(如连接、接收、可读写)已经准备就绪的那些通道。
int n = selector.select();
select方法返回的int值表示有多少通道已经就绪。第一次调用select方法,如果有一个通道就绪,则返回1;如果再次调用select方法,此时另一个通道就绪了,它会再次返回1。我们可以通过Selector的selectedKeys的方法,访问“已选择键集”中的就绪通道
selector.selectedKeys()
while(iterator.hasNext())
{
SelectionKey key = iterator.next();
//通道上是否有可接受的连接
if(key.isAcceptable())
{
ServerSocketChannel ssl = (ServerSocketChannel)key.channel();
SocketChannel scl = ssl.accept();
scl.configureBlocking(false);
scl.register(selector, SelectionKey.OP_READ);
}
//通道上是否有数据可读
else if(key.isReadable())
{
readDataFromSocket(key);
}
iterator.remove();
}
这个循环遍历键集中的每个键,并检测各个键对应的通道的就绪事件并做相应的处理。
我们要注意第17行,调用迭代器的remove方法。Selector不会自己从已选择键集中移除SelectionKey实例,必须要我们自己处理完通道时手动处理。下次该通道变成就绪时,Selector会再次将其放入已选择键集中。
四、WakeUp
某个线程调用select方法阻塞了,即使没有通道就绪,也有办法让其从select返回。只要让其它线程在第一个线程调用select方法的那个对象上调用selector.wakeup方法即可。阻塞在select方法上的线程立马返回。
五、Close
用完selector后调用其close方法会关闭Selector,且使其注册到该Selector上的所有SelectionKey实例无效。通道本身并不会关闭。
JAVA NIO系列(四) 选择器的更多相关文章
- Java NIO系列教程(四) Scatter 和 Gather
Java NIO系列教程(四) Scatter 和 Gather Java NIO 开始支持 scatter/gather,scatter/gather 用于描述从 Channel(译者注:Chann ...
- Java NIO 系列教程(转)
原文中说了最重要的3个概念,Channel 通道Buffer 缓冲区Selector 选择器其中Channel对应以前的流,Buffer不是什么新东西,Selector是因为nio可以使用异步的非堵塞 ...
- Java NIO系列教程(三) Channel之Socket通道
目录: <Java NIO系列教程(二) Channel> <Java NIO系列教程(三) Channel之Socket通道> 在<Java NIO系列教程(二) Ch ...
- Java NIO系列教程(十一) Java NIO 与 IO
Java NIO系列教程(十一) Java NIO与IO 当学习了 Java NIO 和 IO 的 API 后,一个问题马上涌入脑海: 我应该何时使用 IO,何时使用 NIO 呢?在本文中,我会尽量清 ...
- Java NIO系列教程(三-十二) Buffer
原文链接 作者:Jakob Jenkov 译者:airu 校对:丁一 Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到 ...
- Java NIO系列1-概观
Java NIO系列1-概观 Java NIO.中间的N你既可以理解为(new),也就是新的IO,相对于java1.5之前的IO它确实是新的;也可以理解为(no-blocking),也就是非阻塞的IO ...
- Java NIO系列教程(七) selector原理 Epoll版的Selector
目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...
- [转]Java NIO 系列教程
Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(B ...
- Java NIO 系列教程 <转>
Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(B ...
- java NIO系列教程1
ava NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式. Java NIO: Channel ...
随机推荐
- Html5_禁止Html5在手机上屏幕页面缩放
最近测试html5页面,发现默认都允许用户缩放页面,或者在屏幕双击放大或缩小.即相当于这样设置 <meta name="viewport" content="wid ...
- 清除BOM头源码
BOM: Byte Order Mark UTF-8 BOM又叫UTF-8 签名,其实UTF-8 的BOM对UFT-8没有作用,是为了支援UTF-16,UTF-32才加上的BOM,BOM签名的意思就是 ...
- HDU 1421 DP
搬寝室 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- 执行JDBC的executeUpdate()方法时,报错:数据类型不一致,应为number,但却为binary
该原因是因为,在拼写update语句的时候将一个number类型的字段的值赋为了null导致的,如果想将一个number类型的字清空,不能使用null,可以使用“”来替代.
- c++之map
题目描述: 哈利波特在魔法学校的必修课之一就是学习魔咒.据说魔法世界有100000种不同的魔咒,哈利很难全部记住,但是为了对抗强敌,他必须在危急时刻能够调用任何一个需要的魔咒,所以他需要你的帮 ...
- TypeScript学习记录
TypeScript官网 TypeScript中文网 TypeScrpit Handbook 中文版 DefinitelyTyped The TypeScript Definition Manager ...
- linux 解压xz包
1.下载xz包 http://tukaani.org/xz/xz-4.999.9beta.tar.bz2 2.解压安装包 $tar -jxvf xz-4.999.9beta.tar.bz2 3 ...
- DS Tree 已知先序、中序 => 建树 => 求后序
参考:二叉树--前序和中序得到后序 思路历程: 在最初敲的时候,经常会弄混preorder和midorder的元素位置.大体的思路就是在preorder中找到根节点(根节点在序列的左边),然后在mid ...
- app与后台通信协议
通用的语言有很多种,例如英语和中文,在网络的通讯中,通用的协议有很多,其中http是被最广泛使用的.如果是私有的协议,那就只能自己设计了. 用http是最方便的,如果是私有协议,包含协议的封装和拆解, ...
- NGUI 渲染流程深入研究 (UIDrawCall UIGeometry UIPanel UIWidget)
上图是一个简要的NGUI的图形工作流程,UIGeometry被UIWidget实例化之后,通过UIWidget的子类,也就是UISprit,UILabel等,在OnFill()函数里算出所需的Geom ...