深入了解java NIO之Selector(选择器)

 更新时间:2020年07月02日 09:55:46   作者:rickiyang  
这篇文章主要介绍了java NIO之Selector(选择器)的相关资料,文中讲解非常详细,实例代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下

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

下面我们来使用选择器:

通过 Selector.open()方法, 我们可以创建一个选择器:

Selector selector = Selector.open();

将 Channel 注册到选择器中:

channel.configureBlocking(false);

SelectionKey key = channel.register(selector, SelectionKey.OP_READ);

注意, 如果一个 Channel 要注册到 Selector 中, 那么这个 Channel 必须是非阻塞的, 即channel.configureBlocking(false);因为 Channel 必须要是非阻塞的, 因此 FileChannel 不能够使用选择器, 因为 FileChannel 都是阻塞的.

注意到, 在使用 Channel.register()方法时, 第二个参数指定了我们对 Channel 的什么类型的事件感兴趣, 这些事件有:

  • Connect, 即连接事件(TCP 连接), 对应于SelectionKey.OP_CONNECT
  • Accept, 即确认事件, 对应于SelectionKey.OP_ACCEPT
  • Read, 即读事件, 对应于SelectionKey.OP_READ, 表示 buffer 可读.
  • Write, 即写事件, 对应于SelectionKey.OP_WRITE, 表示 buffer 可写.

一个 Channel发出一个事件也可以称为 对于某个事件, Channel 准备好了. 因此一个 Channel 成功连接到了另一个服务器也可以被称为 connect ready.

我们可以使用或运算|来组合多个事件, 例如:

int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;

注意, 一个 Channel 仅仅可以被注册到一个 Selector 一次, 如果将 Channel 注册到 Selector 多次, 那么其实就是相当于更新 SelectionKey 的 interest set. 例如:

channel.register(selector, SelectionKey.OP_READ);
channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

上面的 channel 注册到同一个 Selector 两次了, 那么第二次的注册其实就是相当于更新这个 Channel 的 interest set 为 SelectionKey.OP_READ | SelectionKey.OP_WRITE.

但是Java NIO的selector允许一个单一线程监听多个channel输入。我们可以注册多个channel到selector上,然后然后用一个线程来挑出一个处于可读或者可写状态的channel。selector机制使得单线程管理多个channel变得容易。

下面我们写一个完整的例子,看一下Selector的用法:

//创建选择器
Selector selector = Selector.open();
channel.configureBlocking(false);
//注册通道
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
while(true) {
  //查看selector中的key是否准备好
  int readyChannels = selector.select();
  //小于0超时,等于0没准备好,大于0已经准备完毕
  if(readyChannels == 0) continue;
  //获取选择器中的key
  Set<SelectionKey> selectedKeys = selector.selectedKeys();
  Iterator<SelectionKey> 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();
  }
}

选择器的使用还有很多的细节,我们应该多查看api文档了解各个方法的用法。下一节我们做一个综合练习,总结一下NIO的使用。

以上就是深入了解java NIO之Selector(选择器)的详细内容,更多关于java nio Selector(选择器)的资料请关注脚本之家其它相关文章!

相关文章

  • 如何使用Comparator比较接口实现ArrayList集合排序

    如何使用Comparator比较接口实现ArrayList集合排序

    这篇文章主要介绍了如何使用Comparator比较接口实现ArrayList集合排序问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • Java图形用户界面之列表框

    Java图形用户界面之列表框

    列表框通过Swing组件JList产生,其总是在屏幕上占据固定行数的空间。这篇文章主要介绍了java图形用户界面之列表框的相关资料,非常不错具有参考借鉴价值,需要的朋友可以参考下
    2016-10-10
  • 解决Spring Security的权限配置不生效问题

    解决Spring Security的权限配置不生效问题

    这篇文章主要介绍了解决Spring Security的权限配置不生效问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Java开发学习之Bean的作用域和生命周期详解

    Java开发学习之Bean的作用域和生命周期详解

    这篇文章主要介绍了浅谈Spring中Bean的作用域,生命周期和注解,从创建到消亡的完整过程,例如人从出生到死亡的整个过程就是一个生命周期。本文将通过示例为大家详细讲讲,感兴趣的可以学习一下
    2022-06-06
  • java日期时间操作工具类

    java日期时间操作工具类

    这篇文章主要为大家详细介绍了java日期时间操作工具类,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • SpringBoot+ECharts是如何实现数据可视化的

    SpringBoot+ECharts是如何实现数据可视化的

    今天带大家学习的是关于Java的相关知识,文章围绕着SpringBoot+ECharts怎么实现数据可视化展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • SpringBoot 整合 Lettuce Redis的实现方法

    SpringBoot 整合 Lettuce Redis的实现方法

    这篇文章主要介绍了SpringBoot 整合 Lettuce Redis的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • 深度解析Java中ArrayList的使用

    深度解析Java中ArrayList的使用

    ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。本文将通过示例带你深度解析Java中ArrayList的使用,需要的可以参考一下
    2022-09-09
  • SpringBoot实现邮件推送的详细代码

    SpringBoot实现邮件推送的详细代码

    在项目中经常会遇到SpringBoot推送消息的业务,除了站内推送通知,邮件推送也是一种常见的方式,本文小编就带大家实现邮件推送,文中有详细代码讲解,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-04-04
  • Java 之类型转换与多态详情

    Java 之类型转换与多态详情

    Java使用类创造新的类型(type),并使用继承来便利我们创建类。再深一层讲类型,并是多态(polymorphism)的概念。本文将给大家介绍Java 的类型转换与多态,需要的小伙伴可以参考下面文章的具体内容
    2021-09-09

最新评论