NIO--Selector
目录
概述
Selector
SelectableChannel
SelectionKey
建立选择器
使用选择键
使用选择器
选择过程
停止选择过程
管理选择键
并发性
异步关闭能力
选择过程的可扩展性
概述
Selector
选择器类管理着一个被注册的通道集合的信息和它们的就绪状态。通道是和选择器一起被注册的,并且使用选择器来更新通道的就绪状态。
SelectableChannel
这个抽象类提供了实现通道的可选择性所需要的公共方法。它是所有支持就绪检查的通道类的父类。
SelectableChannel可以被注册到Selector对象上,同时可以指定对那个选择器而言,那种操作是感兴趣的。一个通道可以被注册到多个选择器上,但对每个选择器而言只能被注册一次。
SelectionKey
选择键封装了特定的通道与特定的选择器的注册关系。选择键对象被SelectableChannel.register( ) 返回并提供一个表示这种注册关系的标记。
通道在被注册到一个选择器上之前,必须先设置为非阻塞模式(通过调用configureBlocking(false))。试图注册一个处于阻塞状态的通道,register( )将抛出未检查的IllegalBlockingModeException异常。试图注册一个已经关闭的SelectableChannel实例的话,也将抛出ClosedChannelException异常。
public abstract class Selector implements Closeable {protected Selector() { }public static Selector open() throws IOException {return SelectorProvider.provider().openSelector();}public abstract boolean isOpen();public abstract SelectorProvider provider();public abstract Set<SelectionKey> keys();public abstract Set<SelectionKey> selectedKeys();//非阻塞式,立即返回select数量,可能为0,清除wakeup的调用影响。public abstract int selectNow() throws IOException;//设置了超时的selectpublic abstract int select(long timeout) throws IOException;//阻塞式,仅当 最少返回一个channel,wakeup方法被调用,线程被中断时返回。返回keys数量,可能为0.public abstract int select() throws IOException;//唤醒没有返回的select操作,使立即返回。如果当前没有select操作,则下次select操作会立即返回,触发selectNow被调用。public abstract Selector wakeup();public abstract void close() throws IOException;}
public abstract class SelectionKey
{ public static final int OP_READ ;public static final int OP_WRITE ;public static final int OP_CONNECT ;public static final int OP_ACCEPT ;public abstract SelectableChannel channel( ); public abstract Selector selector( ); public abstract void cancel( ); public abstract boolean isValid( ); public abstract int interestOps( ); public abstract void interestOps (int ops); public abstract int readyOps( );public final boolean isReadable( ) ;public final boolean isWritable( ) ;public final boolean isConnectable( ) ;public final boolean isAcceptable( ) ;public final Object attach (Object ob) ;public final Object attachment( ) ;}
选择器才是提供管理功能的对象,而不是可选择通道对象。选择器对象对注册到它之上的通道执行就绪选择,并管理选择键。
对于键的interest(感兴趣的操作)集合和ready(已经准备好的操作)集合的解释是和特定的通道相关的。每个通道的实现,将定义它自己的选择键类。在register( )方法中构造它并将它传递给所提供的选择器对象。
建立选择器
Selector selector = Selector.open( );
channel1.register (selector, SelectionKey.OP_READ);
channel2.register (selector, SelectionKey.OP_WRITE);
channel3.register (selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
// Wait up to 10 seconds for a channel to become ready
readyCount = selector.select (10000);
有四种被定义的可选择操作:读(read),写(write),连接(connect)和接受(accept)。
并非所有的操作都在所有的可选择通道上被支持。例如,SocketChannel不支持accept。试图注册不支持的操作将导致IllegalArgumentException。您可以通过调用validOps( )方法来获取特定的通道所支持的操作集合。
使用选择键
attach( )方法将在键对象中保存所提供的对象的引用。SelectionKey类除了保存它之外,不会将它用于任何其他用途。
attachment( )方法获取与键关联的附件句柄
SelectionKey key = channel.register (selector, SelectionKey.OP_READ, myObject);
等价于:
SelectionKey key = channel.register (selector, SelectionKey.OP_READ);
key.attach (myObject);
SelectionKey对象是线程安全的,但知道修改interest集合的操作是通过Selector对象进行同步的是很重要
使用选择器
选择过程
keys( )方法返回与选择器关联的已经注册的键的集合,并且可能是空的.这个已注册的键的集合不是可以直接修改的。并不是所有注册过的键都仍然有效。
selectedKeys( )方法返回已经准备好的键的集合,有可能是空的。这是一个键的集合,每个键都关联一个已经准备好至少一种操作的通道。每个键都有一个内嵌的ready集合,指示了所关联的通道已经准备好的操作。
已取消的键的集合(Cancelled key set)是已注册的键的集合的子集,这个集合包含了cancel( )方法被调用过的键(这个键已经被无效化),但它们还没有被注销。
在一个刚初始化的Selector对象中,这三个集合都是空的。
选择操作步骤:
1.已取消的键的集合将会被检查。如果它是非空的,每个已取消的键的集合中的键将从另外两个集合中移除,并且相关的通道将被注销。这个步骤结束后,已取消的键的集合将是空的。
2.已注册的键的集合中的键的interest集合将被检查。在这个步骤中的检查执行过后,对interest集合的改动不会影响剩余的检查过程。
一旦就绪条件被定下来,底层操作系统将会进行查询,以确定每个通道所关心的操作的真实就绪状态。直到系统调用完成为止,这个过程可能会使得调用线程睡眠一段时间,然后当前每个通道的就绪状态将确定下来。对于那些还没准备好的通道将不会执行任何的操作。对于那些操作系统指示至少已经准备好interest集合中的一种操作的通道,将执行以下两种操作中的一种:
a.如果通道的键还没有处于已选择的键的集合中,那么键的ready集合将被清空,然后表示操作系统发现的当前通道已经准备好的操作的比特掩码将被设置。
b.否则,也就是键在已选择的键的集合中。键的ready集合将被表示操作系统发现的当前已经准备好的操作的比特掩码更新。
3.步骤2可能会花费很长时间,特别是所激发的线程处于休眠状态时。与该选择器相关的键可能会同时被取消。当步骤2结束时,步骤1将重新执行,以完成任意一个在选择进行的过程中,键已经被取消的通道的注销。
4.select操作返回的值是ready集合在步骤2中被修改的键的数量,而不是已选择的键的集合中的通道的总数。返回值不是已准备好的通道的总数,而是从上一个select( )调用之后进入就绪状态的通道的数量。之前的调用中就绪的,并且在本次调用中仍然就绪的通道不会被计入,而那些在前一次调用中已经就绪但已经不再处于就绪状态的通道也不会被计入。这些通道可能仍然在已选择的键的集合中,但不会被计入返回值中。返回值可能是0。
停止选择过程
wakeup( ),提供了使线程从被阻塞的select( )方法中优雅地退出的能力.
调用Selector对象的wakeup( )方法将使得选择器上的第一个还没有返回的选择操作立即返回。如果当前没有在进行中的选择,那么下一次对select( )方法的一种形式的调用将立即返回。后续的选择操作将正常进行。在选择操作之间多次调用wakeup( )方法与调用它一次没有什么不同。
如果只想唤醒一个睡眠中的线程,而使得后续的选择继续正常地进行。您可以通过在调用wakeup( )方法后调用selectNow( )方法来绕过这个问题。
管理选择键
选择是累积的。一旦一个选择器将一个键添加到它的已选择的键的集合中,它就不会移除这个键。并且,一旦一个键处于已选择的键的集合中,这个键的ready集合将只会被设置,而不会被清理。
清理一个SelectKey的ready集合的方式是将这个键从已选择的键的集合中移除。选择键的就绪状态只有在选择器对象在选择操作过程中才会修改
并发性
选择器对象是线程安全的,但它们包含的键集合不是。通过keys( )和selectKeys( )返回的键的集合是Selector对象内部的私有的Set对象集合的直接引用。这些集合可能在任意时间被改变。已注册的键的集合是只读的。
异步关闭能力
选择过程的可扩展性
NIO--Selector相关推荐
- java实现一个socks5代理 一了解nio Selector的基本用法
上面浏览器可以放心的将数据交给代理了,接下来做的是怎样处理这些数据,以及面对浏览器突然过来的很多连接如何处理他们,这就要用到javax.nio包下的东西了,下面做简单介绍,不会nio可以先去学习下ni ...
- Java NIO Selector详解(含多人聊天室实例)
一.Java NIO 的核心组件 Java NIO的核心组件包括:Channel(通道),Buffer(缓冲区),Selector(选择器),其中Channel和Buffer比较好理解 简单来说 NI ...
- 四、Java NIO Selector
一.Java NIO 概述 二.Java NIO Channel 三.Java NIO Buffer 四.Java NIO Selector 五.Java NIO 扩展 一.Selector 简介 1 ...
- java nio Selector (新IO)分析
Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样,一个单独的线程可以管理多个channel,从而管理多个网络连接. 为什么 ...
- Java NIO——Selector机制源码分析---转
一直不明白pipe是如何唤醒selector的,所以又去看了jdk的源码(openjdk下载),整理了如下: 以Java nio自带demo : OperationServer.java Oper ...
- NIO : selector、channel、buffer的实例
不同的SelectableChannel所支持的操作是不同的.例如ServerSocketChannel代表一个ServerSocket,它就只支持OP_ACCEPT操作: 当Selector上注册的 ...
- NIO - Selector源码分析
1. 背景 SelectableChannel对象的多路复用器. 可以通过调用Selector.open()方法创建Selector对象.Selector.open()方法会利用系统默认的Select ...
- 深入理解NIO - Selector、ServerSocketChannel、SocketChannel底层原理
IO多路复用模型 IO多路复用需要OS的支持,IO多路复用模型中,引入了一种新的系统调用,查询IO的就绪状态. 在Linux系统中,JavaNIO的Selector#select() 方法对应的系统调 ...
- Java NIO Selector , SelectionKey , SocketChannel , ServerSocketChannel
一 NIO介绍 1. NIO是非阻塞的 NIO非堵塞应用通常适用用在I/O读写等方面,我们知道,系统运行的性能瓶颈通常在I/O读写,包括对端口和文件的操作上,过去,在打开一个I/O通道后,rea ...
- java selector 源码_Java NIO——Selector机制源码分析---转
一直不明白pipe是如何唤醒selector的,所以又去看了jdk的源码(openjdk下载),整理了如下: 以Java nio自带demo : OperationServer.java Oper ...
最新文章
- PHP 删除数组中元素的方式
- 3.1.1蛮力法之选择排序
- HtmlUnit采集页面信息加工并写入excel表
- SAP 电商云 Spartacus UI 从 shipping address 到 shipping method 的 HTTP 请求设计
- android NDK c++ library
- MySQL5.5安装版安装教程
- 一条长为L的绳子,一面靠墙,另外三边组成矩形,问此矩形最大面积能是多少?...
- linux实现防止恶意扫描 PortSentry
- Html页面增加返回顶部图标和隐藏出现
- java mysql大小写_java – 使用select where where Mysql在Mysql中区分大小写
- ROS安装USB摄像头
- 视频剪辑的方法,视频裂变
- 计算机科学与技术专业 ppt,计算机科学与技术专业.ppt
- 7T, 9T and Track
- 知识点滴 - 什么是当量
- 独家 | 爱奇艺如何用大数据助力娱乐工业革命?
- 【Minio】新一代自建文件系统——Minio
- jieba对红楼梦进行分词(一)
- 【ROS Gazebo专题】四、将Fetch机器人放到Gazebo中进行玩耍
- 面试经验之华为暑期实习