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 ...
随机推荐
- HDU 2825 Wireless Password(AC自动机+DP)
题目链接 做题, #include <cstdio> #include <string> #include <cstring> using namespace st ...
- thinkphp常用Config.php配置项
<?php return array( //'配置项'=>'配置值' 'DB_HOST' => 'localhost', 'DB_USER' => 'root', 'DB_PW ...
- jsonkit mrc于arc混编
- svn 回滚到上一个版本shell 脚本
#!/bin/sh ############################## # -- # # author jackluo # # Email net.webjoy@gmail.com # ## ...
- 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行
利用jdk自带的运行监控工具JConsole观察分析Java程序的运行 原文链接 一.JConsole是什么 从Java 5开始 引入了 JConsole.JConsole 是一个内置 Java 性能 ...
- java mail(发送邮件--163邮箱)
package com.util.mail; /** * 发送邮件需要使用的基本信息 */ import java.util.Properties; public class MailSenderIn ...
- Js变量定义——fn里 var与不var的区别
js运行时内置了一个Global对象. 这个Global对象跟运行环境有关.在浏览器运行环境中.Global就是window对象.在nodejs中.Global对象是global对象. 当你在浏览器环 ...
- mysql sql注入
防止SQL注入,我们需要注意以下几个要点: 1.永远不要信任用户的输入.对用户的输入进行校验,可以通过正则表达式,或限制长度:对单引号和 双"-"进行转换等. 2.永远不要使用动态 ...
- 文件代码对比软件 Beyond Compare
Beyond Compare https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=baidu&wd=Beyond%20Co ...
- Mysql和Oracle数据库concat()函数
一.函数的使用参数不同 Mysql支持多个字符串拼接: CONCAT(str1,str2,-) Oralce只支持两个字符串的拼接,若想拼接多个字符串可以嵌套使用concat CONCAT(str1, ...