`

【Java NIO 简例】Selector

    博客分类:
  • Java
nio 
阅读更多

原文:《Java NIO Selector

Selector 可以检查多个 Channel 实例,发现那些已经就绪,可以读/写的 Channel。
通过这个机制,可以实现 单线程处理多个Channel,从而处理多个网络连接

 

为什么要使用 Selector ?

对操作系统来说,线程之间的切换代价较高,而且每个线程都会占用一些内存资源。所以线程越少越好。
而利用Select可以实现只用一个线程处理多个 Channel。

现代操作系统和CPU在多任务处理方面越来越强,多线程开销也更小了。事实上,对于一个多核CPU,如果不采用多任务,可能就是在浪费CPU的算力。但这些属于另一个话题范畴。


 

创建 Selector

Selector selector = Selector.open();

 

将 Channel 注册到 Selector

channel.configureBlocking(false);
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
  • 此处的 Channel 必须设置为 非阻塞 模式。
    FileChannel 没有非阻塞模式,所以它不能与 Selector 共用;SocketChannel 有非阻塞模式,所以它可以。
  • SelectionKey.OP_READ 表示需要监听 Channel 的 Read 事件。
    即,当 Channel 可以被读取时,Selector 会将 OP_READ 加入相应 SelectionKey 的 “已就绪操作集合”中,并把该 SelectionKey 加入 Selector 的 selected-key 集合,供后续操作使用。
Channel 事件及对应的常量值 Channel 事件 常量值 含义
Connect SelectionKey.OP_CONNECT  完成与远程服务器的连接(或连接出错)
Accept SelectionKey.OP_ACCEPT 连接被接受(或出错) 
Read SelectionKey.OP_READ

“读操作”准备就绪

或 已读到数据流的末尾

或 Channel 被连接的另一端关闭

或 出错

Write SelectionKey.OP_WRITE

“写操作” 准备就绪

或 Channel 被连接的另一端关闭

或 出错

 

如果需要监听多个事件,可以用“或”操作连接相应的常量值。如:

int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;

 

SelectionKey

SelectionKey 包含的信息主要有:

  • 监听事件类型集合(Interest Set)
  • 已就绪事件类型集合(Ready Set)
  • Channel
  • Selector
  • 附带的对象(可选)

Interest Set

可通过 SelectionKey.interetOps() 获取该集合,并通过“位操作”来判断是否注册监听了某个事件。

int interestSet = selectionKey.interestOps();

boolean isInterestedInConnect = interestSet & SelectionKey.OP_CONNECT;
boolean isInterestedInAccept = interestSet & SelectionKey.OP_ACCEPT;
boolean isInterestedInRead = interestSet & SelectionKey.OP_READ;
boolean isInterestedInWrite = interestSet & SelectionKey.OP_WRITE;

 

Ready Set

可通过 SelectionKey.readyOps() 获取该集合。
可以像 Interest Set 那样通过“位操作”来判断某个事件是否已发生。
也可以直接调用 SelectionKey 对象相应的方法来判断(内部原理相同)。

int readySet = selectionKey.readyOps();

selectionKey.isConnectable();
selectionKey.isAcceptable();
selectionKey.isReadable();
selectionKey.isWritable();

 

Channel 和 Selector

可通过 SelectionKey 对象相关的方法来获取其对应的 Channel 和 Selector

Channel channel = selectionKey.channel();
Selector selector = selectionKey.selector();

 

附带对象

可将某个对象附带到 SelectionKey 对象上,为后续处理数据提供方便。如,把处理 Channel 数据的 Buffer 对象附带到key上。

selectionKey.attach(obj);
Object attachedObj = selectionKey.attachment();

// 也可在注册Selector时指定附带对象
SelectionKey key = channel.register(selector, SelectionKey.OP_READ, obj);

 

从 Selector 获取就绪的 Channel

可通过 Selector 对象的以下3个方法之一得知是否有 Channel 已就绪。这三个方法都会返回 int,表示已就绪 Channel 的数量

  • select() 阻塞,直到至少有一个 Channel 就绪
  • select(long timeout) 阻塞,直到至少有一个 Channel 就绪 或 超时
  • selectNow() 非阻塞。无论当前有没有 Channel 就绪,都会立即返回

selectedKeys()

如果上述select方法返回的值大于0,即,有Channel就绪,就可以通过 selector 对象的 selectedKeys() 方法获取这些 Channel 对应的 SelectionKey。再通过 SelectionKey 实例获取 Channel 实例并执行后续操作。

Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
  SelectionKey key = keyIterator.next();
  // 处理Channel
  keyIterator.remove();
}

 

Selector.wakeup()

如果一个线程调用了 Selector.select() 方法并发生阻塞,此时另一个线程调用了该 Selector 对象的 wakeup() 方法,则前一个被阻塞的线程将会立即返回。

如果调用 wakeup() 时,没有线程阻塞在 select() 方法,则下一个调用 select() 方法的线程将立即返回。除非期间调用了 selectNow() 方法

 

Selector.close()

如果调用了 Selector 对象的 close() 方法,则 Selector 对象会被关闭,其中的 SelectionKey 实例将失效,但 Channel 不会被关闭

 

完整的 Selector 示例

Selector selector = Selector.open();
channel.configureBlocking(false);
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
while (true) {
  int readyChannelCount = selector.selectNow();
  if (0 == readyChannelCount) {
    continue;
  }

  Set selectedKeys = selector.selectedKeys();
  Iterator keyIterator = selectedKeys.iterator();
  while(keyIterator.hasNext()) {
    SelectionKey key = keyIterator.next();

    if(key.isAcceptable()){
      // 连接已被一个 ServerSocketChannel 接受
    } else if (key.isConnectable()) {
      // 已与远程服务器建立连接
    } else if (key.isReadable()) {
      // “读操作”已准备就绪
    } else if (key.isWritable()) {
      // “写操作”已准备就绪
    }

    keyIterator.remove();
  }
}
  • 大小: 12.6 KB
分享到:
评论

相关推荐

    Java_NIO-Selector.rar_java nio_selector

    Java_NIO类库Selector机制解析 ,很详细 有兴趣可以下载看看。

    Java Nio selector例程

    java侧起server(NioUdpServer1.java),基于Java Nio的selector 阻塞等候,一个android app(NioUdpClient1文件夹)和一个java程序(UI.java)作为两个client分别向该server发数据,server收到后分别打印收到的消息...

    Java_NIO类库Selector机制解析.doc

    Java_NIO类库Selector机制解析.docJava_NIO类库Selector机制解析.docJava_NIO类库Selector机制解析.docJava_NIO类库Selector机制解析.doc

    JavaNIO库Selector机制解析.docx

    JavaNIO库Selector机制解析.docx

    Java NIO——Selector机制解析三(源码分析)

    NULL 博文链接:https://goon.iteye.com/blog/1775421

    Java NIO实战开发多人聊天室

    01-Java NIO-课程简介.mp4 05-Java NIO-Channel-FileChannel详解(一).mp4 06-Java NIO-Channel-FileChannel详解(二).mp4 08-Java NIO-Channel-...23-Java NIO-Selector-示例代码(客户端).mp4 24

    JavaNIO chm帮助文档

    Java NIO系列教程(六) Selector Java NIO系列教程(七) FileChannel Java NIO系列教程(八) SocketChannel Java NIO系列教程(九) ServerSocketChannel Java NIO系列教程(十) Java NIO DatagramChannel Java ...

    java NIO和java并发编程的书籍

    java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...

    Java-NIO类库Selector机制解析.docx

    Java_NIO类库Selector机制解析

    Java-NIO之Selector.doc

    Java-NIO之Selector.doc

    java nio 包读取超大数据文件

    Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据...

    Java NIO Selector选择器简介.pdf

    java NIO Selector选择器简介.pdf

    Java NIO英文高清原版

    Java NIO英文高清原版

    java NIO 中文版

    讲解了 JavaIO 与 JAVA NIO区别,JAVA NIO设计理念,以及JDK中java NIO中语法的使用

    Java NIO 中文 Java NIO 中文 Java NIO 中文文档

    Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...

    java NIO 视频教程

    Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。 Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,...

    java nio 实现socket

    java nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socket

    java nio中文版

    java NIO是 java New IO 的简称,在 jdk1.4 里提供的新 api 。 Sun 官方标榜的特性如下: – 为所有的原始类型提供 (Buffer) 缓存支持。 – 字符集编码解码解决方案。 – Channel :一个新的原始 I/O 抽象。 – 支持...

    java nio Selector的使用-客户端

    NULL 博文链接:https://flym.iteye.com/blog/392373

Global site tag (gtag.js) - Google Analytics