NIO 选择器 Selector

  选择器提供选择执行已经就绪的任务的能力,这使得多元 I/O 成为可能。就像在第一章中描述的那样,就绪选择和多元执行使得单线程能够有效率地同时管理多个 I/O 通道(Channels)。C/C++代码的工具箱中,许多年前就已经有 select()和 poll()这两个POSIX(可移植性操作系统接口)系统调用可供使用了。许过操作系统也提供相似的功能,但对Java 程序员来说,就绪选择功能直到 JDK 1.4 才成为可行的方案。

  从最基础的层面来看,选择器提供了询问通道是否已经准备好执行每个I/0操作的能力。例如,我们需要了解一个SocketChannel对象是否还有更多的字节需要读取,或者我们需要知道ServerSocketChannel是否有需要准备接受的连接。在与SelectableChannel联合使用时,选择器提供了这种服务,但这里面有更多的事情需要去了解。就绪选择的真正价值在于潜在的大量的通道可以同时进行就绪状态的检查。调用者可以轻松地决定多个通道中的哪一个准备好要运行。有两种方式可以选择:被激发的线程可以处于休眠状态,直到一个或者多个注册到选择器的通道就绪,或者它也可以周期性地轮询选择器,看看从上次检查之后,是否有通道处于就绪状态。  乍一看,好像只要非阻塞模式就可以模拟就绪检查功能,但实际上还不够。非阻塞模式同时还会执行您请求的任务,或指出它无法执行这项任务。这与检查它是否能够执行某种类型的操作是不同的。举个例子,如果您试图执行非阻塞操作,并且也执行成功了,您将不仅仅发现read( )是可以执行的,同时您也已经读入了一些数据。就下来您就需要处理这些数据了。效率上的要求需要将检查就绪的代码和处理数据的代码分离开来,至少这么做会很复杂。即使简单地询问每个通道是否已经就绪的方法是可行的,代码需要遍历每一个候选的通道并按顺序进行检查的时候,仍然是有问题的。这会使得在检查每个通道是否就绪时都至少进行一次系统调用,这种代价是十分昂贵的,但是主要的问题是,这种检查不是原子性的。列表中的一个通道都有可能在它被检查之后就绪,但直到下一次轮询为止,您并不会觉察到这种情况。最糟糕的是,除了不断地遍历列表之外将别无选择。因为无法在某个您感兴趣的通道就绪时得到通知。

  真正的就绪选择必须由操作系统来做。操作系统的一项最重要的功能就是处理I/O请求并通知各个线程它们的数据已经准备好了。选择器类提供了这种抽象,使得Java代码能够以可移植的方式,请求底层的操作系统提供就绪选择服务。

执行就绪选择的三个核心类:可选择通道(SelectableChannel) ,选择器(Selector),选择键(SelectionKey)

  可选择通道(SelectableChannel):

    核心方法:

configureBlocking(),isBlocking(),blockingLock()三个方法来配置并检查通道的阻塞模式,通道在被注册到一个选择器上之前,必须先设置为非阻塞模式(通过调用configureBlocking(false))。

  调用可选择通道的register( )方法会将它注册到一个选择器上。如果您试图注册一个处于阻塞状态的通道,register( )将抛出未检查的IllegalBlockingModeException异常。

异常检查代码如下:

            if (!isOpen())
                throw new ClosedChannelException();
            if ((ops & ~validOps()) != 0)
                throw new IllegalArgumentException();
            if (blocking)
                throw new IllegalBlockingModeException();

此外,通道一旦被注册,就不能回到阻塞状态。试图这么做的话,将在调用configureBlocking( )方法时将抛出IllegalBlockingModeException异常,configureBlocking代码如下:

            if (block && haveValidKeys())
                throw new IllegalBlockingModeException();

原文地址:https://www.cnblogs.com/heapStark/p/8178314.html

时间: 2024-10-13 23:24:04

NIO 选择器 Selector的相关文章

Java NIO 选择器(Selector)的内部实现(poll epoll)

http://blog.csdn.net/hsuxu/article/details/9876983 之前强调这么多关于linux内核的poll及epoll,无非是想让大家先有个认识: Java NIO中的选择器依赖操作系统内核的这些系统调用,我们这里只讲解与linux内核相关的NIO实现,当然,windows或其他操作系统实现大体上是类似的,相信大家也可以触类旁通. 那么,本文从这里将从简到难,一步一步为大家讲解选择器的点点滴滴吧. 选择器的宏观理解“有这么一种检查员,她工作在养鸡场,每天的工

NIO组件 Selector(选择器)

简介 使用Selector(选择器), 可以使用一个线程处理多个客户端连接. Selector 能够检测多个注册的通道上是否有事件发生(多个Channel以事件的方式可以注册到同一个Selector), 如果有事件发生, 便获取事件然后针对每个事件进行相应的处理.这样就可以只用一个单线程去管理多个通道, 也就是管理多个连接和请求. 只有在连接有读写事件发生时, 才会进行续写, 就大大地减少了系统开销, 并且不必为每个连接都创建一个线程, 不用去维护多个线程. 避免了多线程之间的上下文切换导致的开

Java NIO 之 Selector 练习

目的:本编文章主要想分享一下NIO方面的知识,由于最近几天工作不忙,趁机学习了下Java NIO Selector的相关知识:主要是实践操作的:具体的理论知识,可以参考网上的文章. 测试用例主要有三种方式: 其实,是服务器端的逻辑不变,客户端有三种方式而已. 服务器端:2个selector + channel, 客户端:一个channel 服务器端:2个selector + channel, 客户端:多个channel(多线程方式) 服务器端:2个selector + channel, 客户端:

JAVA NIO 之 Selector 组件

NIO 重要功能就是实现多路复用.Selector是SelectableChannel对象的多路复用器.一些基础知识: 选择器(Selector):选择器类管理着一个被注册的通道集合的信息和它们的就绪状态. 可选择通道(SelectableChannel):这个抽象类提供了实现通道的可选择性所需要的公共方法.它是所有支持就绪检查的通道类的 父类.例如:ServerSocketChannel.SocketChannel.可选择通道可以被注册到选择器上. 选择键(SelectionKey):选择键封

Flume-NG源码阅读之SourceRunner,及选择器selector和拦截器interceptor的执行

在AbstractConfigurationProvider类中loadSources方法会将所有的source进行封装成SourceRunner放到了Map<String, SourceRunner> sourceRunnerMap之中.相关代码如下: 1 Map<String, String> selectorConfig = context.getSubProperties( 2 BasicConfigurationConstants.CONFIG_SOURCE_CHANNE

利用NIO的Selector处理服务器-客户端模型

内容:这是一个简单的服务器-客户端模型,利用了NIO的Selector来处理多个管道.至于Selector的介绍看这里 NIOServer: public class NIOServer { public static void main(String[] args) throws IOException, InterruptedException { Selector selector = Selector.open(); ServerSocketChannel serverSocketCha

【Android】Android背景选择器selector用法汇总

一.创建xml文件,位置:drawable/xxx.xml,同目录下记得要放相关图片 <?xml version="1.0" encoding="utf-8" ?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 默认时的背景图片--> <item android:drawable="@draw

android 控件选择器Selector

以Button为例: 一般Button有2个状态,按下和正常状态 1.在res下新建drawable文件夹,用以存放自己的Drawable文件 2.在drawable文件夹下新建按下和正常状态shape文件(是图片资源,则略过此步骤) 3.新建Button背景Selector文件 4.为Button的backgroud指定Drawable 代码: button_noraml.xml <?xml version="1.0" encoding="utf-8"?&g

Java NIO类库Selector机制解析--转

一.  前言 自从J2SE 1.4版本以来,JDK发布了全新的I/O类库,简称NIO,其不但引入了全新的高效的I/O机制,同时,也引入了多路复用的异步模式.NIO的包中主要包含了这样几种抽象数据类型: Buffer:包含数据且用于读写的线形表结构.其中还提供了一个特殊类用于内存映射文件的I/O操作. Charset:它提供Unicode字符串影射到字节序列以及逆映射的操作. Channels:包含socket,file和pipe三种管道,都是全双工的通道. Selector:多个异步I/O操作集