`
zachary.guo
  • 浏览: 487256 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

NIO - 选择器基础

    博客分类:
  • NIO
阅读更多
    ◇ 选择器、可选择通道和选择键类
        实际上,与选择器相关的类的 api 有三个,它们用于执行就绪选择:

  • 选择器(Selector):选择器类管理着一个被注册的通道集合的信息和它们的就绪状态。通道是和选择器一起被注册的,并且使用选择器来更新通道的就绪状态。
  •        
  • 可选择通道(SelectableChannel):它是所有支持就绪检查的通道类的父类。FileChannel 对象不是可选择的,因为它没有继承 SelectableChannel。所有 socket 通道都是可选择的,包括从管道(Pipe)对象的中获得的通道。只有 SelectableChannel 可以被注册到 Selector 对象上。一个通道可以被注册到多个选择器上,但对每个选择器而言只能被注册一次。
  •        
  • 选择键(SelectionKey):选择键封装了特定的通道与特定的选择器的注册关系。选择键对象被 SelectableChannel.register() 返回并提供一个表示这种注册关系的标记。选择键包含了两个比特集(以整数的形式进行编码),指示了该注册关系所关心的通道操作,以及通道已经准备好的操作。
SelectableChannel 的相关API方法:
public abstract class SelectableChannel extends AbstractChannel implements Channel {
    // This is a partial API listing
    public abstract SelectionKey register(Selector sel, int ops)
        throws ClosedChannelException;
    public abstract SelectionKey register(Selector sel, int ops, Object att)
        throws ClosedChannelException;
    public abstract boolean isRegistered();
    public abstract SelectionKey keyFor(Selector sel);
    public abstract int validOps();
    public abstract void configureBlocking(boolean block) throws IOException;
    public abstract boolean isBlocking();
    public abstract Object blockingLock();
}

        调用 SelectableChannel 的 register() 方法会将它注册到一个选择器上。如果你试图注册一个处于阻塞状态的通道,register() 将抛出未检查的 IllegalBlockingModeException 异常。此外,通道一旦被注册,就不能回到阻塞状态。试图这么做的话,将在调用 configureBlocking() 方法时将抛出 IllegalBlockingModeException 异常。并且,理所当然地,试图注册一个已经关闭的 SelectableChannel 实例的话,也将抛出 ClosedChannelException 异常,就像方法原型指示的那样。通道在被注册到一个选择器上之前,必须先设置为非阻塞模式(通过调用configureBlocking(false))。

Selector 的相关 API 方法:
public abstract class Selector {
    public static Selector open() throws IOException
    public abstract boolean isOpen();
    public abstract void close() throws IOException;
    public abstract SelectionProvider provider();
    public abstract int select() throws IOException;
    public abstract int select(long timeout) throws IOException;
    public abstract int selectNow() throws IOException;
    public abstract void wakeup();
    public abstract Set keys();
    public abstract Set selectedKeys();
}

        选择器维护了一个需要监控的通道的集合。一个给定的通道可以被注册到多于一个的选择器上,而且不需要知道它被注册了哪个 Selector 对象上。SelectableChannel 的 register() 将返回一个封装了两个对象的关系的选择键对象。

SelectionKey 的相关 API 方法:
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();
}

        选择器才是提供管理功能的对象,而不是可选择通道对象。选择器对象对注册到它之上的通道执行就绪选择,并管理选择键。

    ◇ 建立选择器
        来看一段简短的代码,以便能够帮助我们将所有东西放到一个特定的上下文中去理解。为了建立监控三个 Socket 通道的选择器,你需要做像这样的事情:
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);

        上面的代码创建了一个新的选择器,然后将这三个(已经存在的) socket 通道注册到选择器上,而且感兴趣的操作各不相同。 select() 方法在将线程置于睡眠状态,直到这些刚兴趣的事情中的操作中的一个发生或者 10 秒钟的时间过去。

        Selector 对象是通过调用静态工厂方法 open() 来实例化的。选择器不是像通道或流(stream)那样的基本 I/O 对象:数据从来没有通过它们进行传递。当你不再使用 Selector 时,需要调用 close() 方法来释放它可能占用的资源并将所有相关的选择键设置为无效。一旦一个选择器被关闭,试图调用它的大多数方法都将导致 ClosedSelectorException。注意 ClosedSelectorException 是一个运行时的)错误。你可以通过 isOpen() 方法来测试一个选择器是否处于被打开的状态。

        SelectableChannel 的 register() 方法接受一个 Selector 对象作为参数,以及一个名为 ops 的整数参数。第二个参数表示所关心的通道操作。这是一个表示选择器在检查通道就绪状态时需要关心的操作的比特掩码。JDK 中有四种被定义的可选择操作:读(read),写(write),连接(connect)和接受(accept)。并非所有的操作都在所有的可选择通道上被支持。例如,SocketChannel 不支持 accept。试图注册不支持的操作将导致 IllegalArgumentException。你可以通过调用 SelectableChannel 的 validOps() 方法来获取特定的通道所支持的操作集合。
分享到:
评论

相关推荐

    httpcore-nio-4.3.jar包

    NIO的核心概念包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。通道可以读写数据,缓冲区用于临时存储数据,选择器则用于监听多个通道的事件,实现了多路复用,从而实现非阻塞I/O。 3. **HttpCore NIO...

    httpcore-nio-4.4.6.zip

    1. **高性能爬虫**:HTTPCore-NIO的高效连接管理和非阻塞特性使其成为构建高性能网络爬虫的理想选择,可以轻松处理大量并发请求。 2. **微服务通信**:在微服务架构中,HTTPCore-NIO可以作为服务间通信的基础,提供...

    SocketIO-BIO-NIO-AIO.zip

    此外,NIO还提供了选择器(Selectors),可以监控多个通道的状态,提高了服务器的并发处理能力。 **3. AIO(异步I/O)** AIO,也称为NIO.2,进一步优化了I/O模型。在AIO中,读写操作是非阻塞的,并且操作系统会在...

    java网络编程NIO视频教程

    - **主要内容**:介绍Selector(选择器)的概念及其在多路复用中的作用。 - **学习目标**:理解Selector的基本原理。 #### 22. Java NIO-Selector-操作方法 - **主要内容**:详细讲解Selector的操作方法,如注册、...

    【IT十八掌徐培成】Java基础第27天-02.NIO-ServerSocketChannel-SocketChannel.zip

    通过使用Selector,我们可以设计出一种选择器模式,将多个通道注册到同一个选择器上,然后在单个线程中轮询选择器,处理那些准备好的通道,从而实现高并发的网络服务。 总的来说,本教程将围绕ServerSocketChannel...

    Java中的IO与NIO-jiava求职面试-15题,答案

    此外,NIO还提供了选择器(Selector),允许单个线程管理多个通道,提高了并发处理能力,尤其适用于大量连接的服务器端应用。 在IO模型方面,面试中可能会考察阻塞IO、非阻塞IO和多路复用IO。阻塞IO是最基础的模型...

    Java视频教程 Java游戏服务器端开发 Netty NIO AIO Mina视频教程

    [第9节] Java NIO流-选择器操作.flv 四、Mina视频教程 00、Mina视频课程介绍.flv 01、Mina服务端helloWorld入门.flv 02、Mina客户端helloWorld入门.flv 03、Mina整体体系结构分析.flv 04、Mina学习之长短连接....

    BIO、NIO、AIO、Netty 、TCP全网最全解析!Netty中提供了哪些线程模型?

    NIO通过选择器(Selector)实现,一个线程可以管理多个通道(Channel),提高了系统的并行性。然而,NIO的编程模型相对复杂,需要开发者处理更多的细节。 3. **AIO(异步I/O)**:Java 7引入了AIO,也称为NIO.2。...

    具有增强的超电容性能的形状可控的NiO-石墨烯纳米复合材料的合成

    相比之下,电化学电容器(也称为超级电容器)在提供快速能量传输和再充电(即高功率密度)方面是极佳的选择。 超级电容器可以通过不同的能量存储机制被分为两类:电化学双层电容器(EDLCs)和赝电容器。而本研究...

    Java NIO Selector选择器简介.pdf

    ### Java NIO Selector选择器详解 #### 一、Selector概览及作用 **Selector** 是 Java NIO (New I/O) 框架中的一个重要组成部分,主要用于检测一个或多个 **NIO Channel** 的状态,包括但不限于可读、可写、可连接...

    NIO项目源码.zip

    - 流量控制:NIO可以通过选择器实现基于事件驱动的流量控制,避免无谓的等待。 5. NIO与BIO的区别 - BIO是同步且阻塞的,一个线程处理一个连接,当连接空闲时线程也会阻塞等待。 - NIO是同步但非阻塞的,一个...

    Java语言基础教程-Java NIO流篇2

    这可能包括如何通过选择器(Selector)进行多路复用,即一个线程可以监听多个通道的事件,从而实现非阻塞I/O。选择器的使用大大提高了服务器处理大量并发连接的能力。 第6节将聚焦于Java NIO中的Socket通道操作,这...

    Java语言基础教程-Java NIO流篇1

    理解并熟练掌握这些内容,将为后续深入学习NIO的其他高级特性,如选择器、多路复用等打下坚实的基础。在实际开发中,NIO可以帮助我们构建更加高效、灵活的网络服务,尤其在处理大量并发连接时,NIO的优势更为明显。

    基于Java NIO反应器模式设计与实现

    Java NIO的反应器模式设计与实现,首先涉及到理解Java NIO的基本概念,如通道(Channel)、缓冲区(Buffer)、选择器(Selector)等。通道是进行读写操作的基础,是连接I/O源和数据的端点。缓冲区是在NIO中用于数据...

    网络编程(socket、NIO、mina)---demo

    而NIO引入了选择器(Selector)和通道(Channel)的概念,允许单个线程同时管理多个连接,显著减少了线程的创建和管理开销。在Java中,`java.nio.channels`包提供了对NIO的支持,如`ServerSocketChannel`和`...

    Java语言基础教程-Java NIO流篇3

    在本教程中,我们将深入探讨Java NIO流的两个关键部分:文件通道操作和选择器。 ### 文件通道操作 在Java NIO中,文件通道(FileChannel)是从`java.nio.channels.FileChannel`类中创建的,它允许我们以非阻塞方式...

    Java NIO 英文版

    选择器是NIO的一个核心组件,它允许单个线程监视多个输入通道。可以注册多个通道到选择器上,并且可以配置它们关注的I/O事件,如读、写或连接。当某个事件发生时,选择器会通知应用程序,从而允许非阻塞式的I/O。 ...

    NIO编程实现实例

    而NIO引入了非阻塞I/O和选择器(Selector),使得单个线程可以同时处理多个连接,从而提高了服务器的并发能力。 NIO的核心组件包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。通道是数据读写的基础,...

    nio入门文档及示例代码

    3. **选择器使用示例**:如何创建和使用选择器,以及处理选择器返回的事件。 通过这些示例,你可以深入了解NIO在实际项目中的应用,更好地理解和掌握Java NIO API的使用技巧。在学习过程中,建议结合具体代码逐行...

Global site tag (gtag.js) - Google Analytics