前面介绍过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

表示 SelectableChannelSelector 中的注册的标记,每次向选择器注册通道时就会创建一个选择键。选择键中包含的内容有:

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实例无效。通道本身并不会关闭。

最新文章

  1. SQL 2008 R2下载 升级R2 SP1或者SQL 2008从10.50.1600升级10.5.2500
  2. 安装PyMysql的基本步骤
  3. javascript-this,call,apply,bind简述1
  4. sc 与net命令的区别
  5. AFNetworking实现程序重新启动时的断点续传
  6. 学习开发jquery插件
  7. 关于SSH框架设计的一些理解
  8. docker-compose 所带来的方便
  9. 使用Recovery Services备份文件及文件夹
  10. 分享一个集成在项目中的REST APIs文档框架swagger
  11. 1分钟解决VS每次运行都显示“正在还原nuget程序包”问题
  12. pycharm创建scrapy项目教程及遇到的坑
  13. Linux系统中yum 命令讲解
  14. 实现本地svn目录同步时,服务器的相应目录保持自动同步
  15. HttpClient学习记录-系列1(tutorial)
  16. C#_方法的重载
  17. Tarjan求缩点化强连通图
  18. Lighttpd1.4.20源代码分析 笔记 状态机之错误处理和连接关闭
  19. Python: 字符串搜索和匹配,re.compile() 编译正则表达式字符串,然后使用match() , findall() 或者finditer() 等方法
  20. 初始化css文件

热门文章

  1. Java_动态加载
  2. Hbase1.0 客户端api
  3. osg中使用MatrixTransform来实现模型的平移/旋转/缩放
  4. angular.js学习笔记之一
  5. PHP后门新玩法:一款猥琐的PHP后门分析
  6. mysql 命令管理
  7. jquery_选择器
  8. IOS第四天(1:图片的方法和缩小,遮罩层)
  9. document获取节点byId&byName
  10. jquery 绑定事件的方法