Selector是个啥?
Selector是Java NIO核心组件中的选择器,用于检查一个或多个Channel(通道)的状态是否处于可读、可写。实现一个单独的线程可以管理多个channel,从而管理多个网络连接。使用一个线程进行处理,也避免了线程上下文切换带来的开销。
而在传统IO模型下,服务器处理请求就是accept()方法阻塞等待请求进来,有请求连接之后,创建一个线程去保持连接直到socket关闭。虽然你可以采用复用线程池的方式减少开销,但在应对大量请求时,也无可避免的会造成性能问题。
继承关系图
抽象类方法
Selector是一个抽象类,并没有写什么具体实现。我们先简单看看有哪些功能。
public abstract class Selector implements Closeable {
// 构造方法
protected Selector() { }
// 打开选择器
public static Selector open() throws IOException {
return SelectorProvider.provider().openSelector();
}
// 判断此选择器是否已打开。
public abstract boolean isOpen();
// 返回创建Channel的选择器生产者
public abstract SelectorProvider provider();
// 返回选择器的key set
public abstract Set<SelectionKey> keys();
// 返回此选择器的selected-key集。
public abstract Set<SelectionKey> selectedKeys();
// 对选择的一组键所对应的通道准备进行IO操作。
public abstract int selectNow() throws IOException;
public abstract int select(long timeout)
throws IOException;
public abstract int select() throws IOException;
// 唤醒阻塞在selector.select上的线程,让该线程及时去处理其他事情,
// 例如注册channel,改变interestOps、判断超时等等。
public abstract Selector wakeup();
// 关闭选择器
public abstract void close() throws IOException;
}
SelectableChannel是个啥?
SelectableChannel提供了实现通道的可选择性所需要的公共方法。它是所有支持就绪检查的通道类的父类。继承了SelectableChannel类的Channel都是可选择的。而FileChannel类并没有继承SelectableChannel,因此不是可选通道。
PS:一个通道可以被注册到多个选择器上,但对于每个选择器而言只能被注册一次。
抽象类方法
public abstract class SelectableChannel
extends AbstractInterruptibleChannel
implements Channel
{
// 构造方法
protected SelectableChannel() { }
// 返回创建Channel的选择器生产者
public abstract SelectorProvider provider();
// 返回有效操作集
public abstract int validOps();
// 判断此Channel是否在Selector中注册
public abstract boolean isRegistered();
// 返回Channel在Selector中的注册的选择键
public abstract SelectionKey keyFor(Selector sel);
public abstract SelectionKey register(Selector sel, int ops, Object att)
throws ClosedChannelException;
public final SelectionKey register(Selector sel, int ops)
throws ClosedChannelException
{
return register(sel, ops, null);
}
// 调整此通道为阻塞模式。
public abstract SelectableChannel configureBlocking(boolean block)
throws IOException;
// 调整此通道是否阻塞
public abstract boolean isBlocking();
// 返还阻塞模式锁定的对象
public abstract Object blockingLock();
}
SelectionKey是个啥?
SelectionKey顾名思义选择键,选择键中包含了注册在Selector的通道操作的类型,也包含了了特定的通道与特定的选择器的注册关系。
Channel和Selector进行绑定,一旦通道处于某种就绪的状态,就可以被Selector感知。Selector会根据对应的选择键,进行不同的业务逻辑处理。
继承关系图
aaarticlea/png;base64,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" alt="" />
抽象类方法
public abstract class SelectionKey {
// 构造方法
protected SelectionKey() { }
// 返回当前选择键对应的SelectableChannel
public abstract SelectableChannel channel();
// 返回当前选择键对应的Selector
public abstract Selector selector();
// 判断当前选择键是否有效。
public abstract boolean isValid();
// 取消特定的注册关系。
public abstract void cancel();
// selector中感兴趣的集合
public abstract int interestOps();
public abstract SelectionKey interestOps(int ops);
// 获取相关通道已经就绪的操作
public abstract int readyOps();
// SelectionKey中的四种操作类型:读、写、连接、接受。
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;
public final boolean isReadable() {
return (readyOps() & OP_READ) != 0;
}
public final boolean isWritable() {
return (readyOps() & OP_WRITE) != 0;
}
public final boolean isConnectable() {
return (readyOps() & OP_CONNECT) != 0;
}
public final boolean isAcceptable() {
return (readyOps() & OP_ACCEPT) != 0;
}
// SelectionKey上的附加对象
private volatile Object attachment = null;
private static final AtomicReferenceFieldUpdater<SelectionKey,Object>
attachmentUpdater = AtomicReferenceFieldUpdater.newUpdater(
SelectionKey.class, Object.class, "attachment"
);
// 将附加对象绑定到SelectionKey上,便于识别给定的通道
public final Object attach(Object ob) {
return attachmentUpdater.getAndSet(this, ob);
}
// 取出绑定在SelectionKey上的附加对象
public final Object attachment() {
return attachment;
}
}
关键方法解析
在了解了Selector,SelectableChannel,SelectionKey的概念后,我们进一步深入源码
open方法
打开选择器,创建Selector对象
public static Selector open() throws IOException {
return SelectorProvider.provider().openSelector();
}
SelectorProvider的静态方法provider
public static SelectorProvider provider() {
synchronized (lock) {
// 判断provider是否已经产生,若已产生则直接返回
if (provider != null)
return provider;
// 若未产生,则需要调用AccessController的静态方法doPrivileged,创建一个新的Selector对象
return AccessController.doPrivileged(
new PrivilegedAction<SelectorProvider>() {
public SelectorProvider run() {
if (loadProviderFromProperty())
return provider;
if (loadProviderAsService())
return provider;
provider = sun.nio.ch.DefaultSelectorProvider.create();
return provider;
}
});
}
}
select方法
// 由其基类SelectorImpl中实现
public int select() throws IOException {
return this.select(0L);
}
public int select(long var1) throws IOException {
if (var1 < 0L) {
throw new IllegalArgumentException("Negative timeout");
} else {
// slect()无参时默认传入0,实则交给lockAndDoSelect方法去完成,并且令参数为-1
return this.lockAndDoSelect(var1 == 0L ? -1L : var1);
}
}
private int lockAndDoSelect(long var1) throws IOException {
synchronized(this) {
// 先判断当前的Selector对象是否关闭
if (!this.isOpen()) {
throw new ClosedSelectorException();
} else {
// 分别以publicKeys以及publicSelectedKeys为锁,最终的实现交给抽象方法doSelect完成;
int var10000;
synchronized(this.publicKeys) {
synchronized(this.publicSelectedKeys) {
// doSelect方法由WindowsSelectorImpl实现
var10000 = this.doSelect(var1);
}
}
return var10000;
}
}
}
doSelect方法由WindowsSelectorImpl实现:
// channelArray是一个SelectionKeyImpl数组,SelectionKeyImpl负责记录Channel和SelectionKey状态
// channelArray是根据连接的Channel数量动态维持的,初始化大小是8。
private SelectionKeyImpl[] channelArray = new SelectionKeyImpl[8];
protected int doSelect(long var1) throws IOException {
if (this.channelArray == null) {
throw new ClosedSelectorException();
} else {
this.timeout = var1;
// 调用processDeregisterQueue方法来取消准备撤销的集合
this.processDeregisterQueue();
if (this.interruptTriggered) {
// 若是发生了中断,调用resetWakeupSocket方法恢复中断
this.resetWakeupSocket();
return 0;
} else {
// 未发生中断,调用adjustThreadsCount调整轮询线程数量
this.adjustThreadsCount();
this.finishLock.reset();
this.startLock.startThreads();
try {
this.begin();
try {
this.subSelector.poll();
} catch (IOException var7) {
this.finishLock.setException(var7);
}
if (this.threads.size() > 0) {
this.finishLock.waitForHelperThreads();
}
} finally {
this.end();
}
this.finishLock.checkForException();
this.processDeregisterQueue();
int var3 = this.updateSelectedKeys();
this.resetWakeupSocket();
return var3;
}
}
}
Selector使用示例
服务端
public static void main(String[] args) throws Exception {
try {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress("127.0.0.1", 8000));
ssc.configureBlocking(false);
Selector selector = Selector.open();
// 注册 channel,并且指定感兴趣的事件是 Accept
ssc.register(selector, SelectionKey.OP_ACCEPT);
ByteBuffer readBuff = ByteBuffer.allocate(1024);
ByteBuffer writeBuff = ByteBuffer.allocate(128);
writeBuff.put("received".getBytes());
writeBuff.flip();
while (true) {
int nReady = selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> it = keys.iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
it.remove();
if (key.isAcceptable()) {
// 创建新的连接,并且把连接注册到selector上
// 声明这个channel只对读操作感兴趣。
SocketChannel socketChannel = ssc.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
}
else if (key.isReadable()) {
SocketChannel socketChannel = (SocketChannel) key.channel();
readBuff.clear();
socketChannel.read(readBuff);
readBuff.flip();
System.out.println("received : " + new String(readBuff.array()));
key.interestOps(SelectionKey.OP_WRITE);
}
else if (key.isWritable()) {
writeBuff.rewind();
SocketChannel socketChannel = (SocketChannel) key.channel();
socketChannel.write(writeBuff);
key.interestOps(SelectionKey.OP_READ);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
客户端
public static void main(String[] args) throws Exception {
try {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1", 8000));
ByteBuffer writeBuffer = ByteBuffer.allocate(32);
ByteBuffer readBuffer = ByteBuffer.allocate(32);
writeBuffer.put("hello".getBytes());
writeBuffer.flip();
while (true) {
Thread.sleep(1000);
writeBuffer.rewind();
socketChannel.write(writeBuffer);
readBuffer.clear();
socketChannel.read(readBuffer);
}
} catch (IOException e) {
}
}
- Java NIO类库Selector机制解析(下)
五. 迷惑不解 : 为什么要自己消耗资源? 令人不解的是为什么我们的Java的New I/O要设计成这个样子?如果说老的I/O不能多路复用,如下图所示,要开N多的线程去挨个侦听每一个Channel ...
- Java NIO类库Selector机制解析(上)
一. 前言 自从J2SE 1.4版本以来,JDK发布了全新的I/O类库,简称NIO,其不但引入了全新的高效的I/O机制,同时,也引入了多路复用的异步模式.NIO的包中主要包含了这样几种抽象数据类型: ...
- Java NIO类库Selector机制解析--转
一. 前言 自从J2SE 1.4版本以来,JDK发布了全新的I/O类库,简称NIO,其不但引入了全新的高效的I/O机制,同时,也引入了多路复用的异步模式.NIO的包中主要包含了这样几种抽象数据类型: ...
- NIO(三):Selector选择器
一.堵塞式与非堵塞式 在传统IO中,将数据由当前线程从客户端传入服务端,由服务端的内核进行判断传过来的数据是否合法,内核中是否存在数据. 如果不存在数据 ,并且数据并不合法,当前线程将会堵塞等待.当前 ...
- U盘装系统系列三—-ghost系统安装教程
前面和大家分享了如何用老毛桃U盘启动盘制作工具把U盘制作启动盘,接下来说下制作好启动盘之后如何安装ghost系统.首先我们准备好ghost镜像复制到U盘中:然后用U盘启动:选择[01]后按Enter键 ...
- Linux U盘 启动盘
/****************************************************************************** * Linux U盘 启动盘 * 说明: ...
- windows下制作linux U盘启动盘或者安装优盘(转)
windows下制作linux U盘启动盘或者安装优盘(转) Linux发行版排行榜:http://iso.linuxquestions.org/ [方案一]:UltraISO(不推荐,在Window ...
- Windows-002-U盘启动盘制作
通常我们安装系统时,均采用光盘的形式安装,只是这种方法需要随时随地的带着光盘,还不容易保存.携带光盘.这时,一个 U盘启动盘 就是您的首选了,此种方式的好处多多,比如:忘记开机密码.系统备份.安装系统 ...
- 一键制作u盘启动盘教程
第一步:制作完成u深度u盘启动盘 第二步:下载Ghost Win7系统镜像文件包,存入u盘启动盘 第三步:电脑模式更改成ahci模式,不然安装完成win7系统会出现蓝屏现象 正式安装步骤: u ...
- windows和linux环境下制作U盘启动盘
新笔记本上,要装xp的系统,100%会破坏原有的Linux系统,因为安装xp的时候会自动覆盖硬盘的主引导扇区,这个扇区一旦被重写,那么原有的linux根本就启动不了. 要想玩linux和xp双系统,一 ...
随机推荐
- 通过windug判断某个模块导致程序不能退出。
1.windug附加进程. 2.~* kb 3.看堆栈
- [USACO09FEB]股票市场Stock Market
题意简述: 给定⼀个DDD天的SSS只股票价格矩阵,以及初始资⾦ MMM:每次买股票只能买某个股票价格的整数倍,可以不花钱,约定获利不超过500000500000500000.最⼤化你的 总获利. 题 ...
- [系列] Gin框架 - 数据绑定和验证
目录 概述 推荐阅读 概述 上篇文章分享了 Gin 框架使用 Logrus 进行日志记录,这篇文章分享 Gin 框架的数据绑定与验证. 有读者咨询我一个问题,如何让框架的运行日志不输出控制台? 解决方 ...
- Spring Cloud 之 Config与动态路由.
一.简介 Spring Cloud Confg 是用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,它分为服务端与客户端两个部分.其中服务端也称为分布式配置中心,它是一个独立的微服务 ...
- 【iOS】Apple Mach-O Linker Error Linker command failed with exit code 1
又遇到了这个问题,貌似之前遇到过……如图所示: 解决方法寻找中………… 在 Stack Overflow 找到了解决方法,如下: 参考链接:Apple Mach-O Linker Error
- Could not load NIB in bundle: 'NSBundle.....
学习NSNotification时遇到了这个问题,错误日志如下: 2015-08-28 17:47:24.617 NSNotificationDemo[7158:786614] *** Termina ...
- JAVA-Spring AOP五大通知类型
一.前置通知 在目标方法执行之前执行的通知 在前置通知方法,可以没有参数,也可以额外接收一个JoinPoint,Spring会自动将该对象传入,代表当前的连接点,通过该对象可以获取目标对象和目标方法相 ...
- python利用select实现的Socket Server
# 利用python的select模块实现简单的Socket Sever #实现多用户访问,再次基础上可以实现FTP Server应用程序 # 发布目的,在于解决了客户端强行终止时,服务器端也跟着程序 ...
- oracle实战(一)
一.表空间的创建以及删除 声明:此操作环境为windows,oracle10G 表空间? ORACLE数据库的逻辑单元. 数据库---表空间 一个表空间可以与多个数据文件(物理结构)关联 一个数据库下 ...
- jdk8与jdk7中hashMap的resize分析
在分析代码之前,我们先抛出下面的问题: hashmap 扩容时每个 entry 需要再计算一次 hash 吗? 我们首先看看jdk7中的hashmap的resize实现 1 void resize(i ...