返回顶部
首页 > 资讯 > 精选 >Java NIO中Selector是什么
  • 786
分享到

Java NIO中Selector是什么

2023-06-29 02:06:21 786人浏览 八月长安
摘要

这篇文章将为大家详细讲解有关Java NIO中Selector是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、Selector 简介1、Selector 和 Channel 关系Sele

这篇文章将为大家详细讲解有关Java NIO中Selector是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

一、Selector 简介

1、Selector 和 Channel 关系

Selector 一般称为选择器,可以翻译为 多路复用。它是 Java Nio 核心组件中的一个,用于检查一个或者多个 NIO Channel (通道) 的状态是否处于可读、可写。如此可以实现单线程管理多个 Channels , 也就是可以管理多个网络链接。

Java NIO中Selector是什么

使用 Selector 的好处在于:使用更少的线程就可以来处理通道了,相比使用多个线程,避免了线程上下文切换带来的开销。

2、可选择通道(SelectableChannel)

(1)不是所有的 Channel 都是可以被 Selector 复用的。比方说, FileChannel 就不能被选择器复用。判断一个 Channel 能被 Selector 复用,有一个前提:判断他是否继承了一个抽象类 SelectableChannel。如果继承了 SelectableChannel , 则可以被复用,否则不能。

(2)SelectableChannel 提供了实现通道选择性所需要的公共方法。它是所有支持就绪检查通道类的父类,所有 Socket 通道,都继承 SelectableChannel 类都是可选择的,包括从管道(Pipe) 对象的中获取得到的通道。而 FileChannel 类,没有继承 SelectableChannel , 因此是不是可选通道。

(3)一个通道可以被注册到多个选择器上,但对每个选择器而言只能被注册一次。通道和选择器之间的关系,使用注册的方式完成。SelectableChannel 可以被注册到 Selector 对象上,在注册时候,需要指定通道的那些操作,是 Selector 感兴趣的。

Java NIO中Selector是什么

3、Channel 注册到 Selector

(1)使用Channel.reGISter(Selector sel, int pos) 方法,将一个通道注册到一个选择器时。第一个参数,指定通道要注册的选择器。第二个参数指定选择器需要查询的通道操作。

(2)可供选择器查询的通道操作,从类型类分,包括一下四种:

  • 可读:SelectionKey.OP_READ

  • 可写:SelectionKey.OP_WRITE

  • 连接:SelectionKey.OP_CONNECT

  • 接收:SelectionKey.OP_ACCEPT

如果 Selector 对通道的多操作类型感兴趣,可以用“位或”操作符来实现:

比如int key = SelectionKey.OP_READ | SelectionKey.OP_WRITE;

(3)选择器查询的不是通道的操作,而是通道的某个操作的一种就绪状态。什么操作的就绪状态?一旦通道具备完成某个操作的条件,表示该通道的某个操作已经就绪,就可以被 Selector 查询到,程序可以对通道进行对应的操作。比方说,某个 SocketChannel 通道可以连接到一个服务器,则处于“连接就绪”状态(OP_CONNECT)。 再比方说,一个ServerSocketChannel 服务器通道准备好接收新进入的连接,则处于“接收就绪”(OP_ACCEPT)状态。还比方说,一个数据可读的通道,可以说是“读就绪”(OP_READ)。一个等待写数据的通道可以说是“写就绪”(OP_WRITE)。

4、选择键(SelectionKey)

(1)Channel 注册之后,并且一旦通道处于某种就绪状态,就可以被选择器查询到。这个工作使用选择器 Selector 的 select() 方法完成。select 方法的作用,对感兴趣的通道操作,进行就绪状态的查询。

(2)Selector 可以不断的查询 Channel 中发生的操作的就绪状态。并且选择甘心去的操作就绪状态。一旦通道有操作的就绪状态达成,并且是 Selecor 感兴趣的操作,就会被 Selector 选中,放入选择键集合中。

(3)一个选择键,首先包含了注册在 Selector 的通道操作的类型,比方说: SelectionKey.OP_READ . 也包含了特定的通道与特定的选择器之间的注册关系。

开发应用程序是,选择键是编程的关键,NIO 编程,就是更具对应的选择键,进行不同的业务逻辑处理。

(4)选择键的概念,和事件的概念比较相似。一个选择键类似监听器模式里面的一个事件。由于 Selector 不是事件触发的模式,而是主动去查询的模式,所以不叫事件 Event, 而是叫 SelectionKey 选择键。

二、Selector 的使用方法

1、Selector 的创建

通过 Selector.open() 方法创建一个 Selector 对象。如下;

// 获取 Selector 选择器Selector selector = Selector.open();

2、注册 Channel 到 Selector

要实现 Selector 管理 Channel , 需要将 channel 注册到相应的 Selector 上

// 1. 获取 Selector 选择器Selector selector = Selector.open();// 2. 获取通道ServerSocketChannel socketChannel = ServerSocketChannel.open();// 3. 设置为非阻塞socketChannel.configureBlocking(false);// 4. 绑定连接socketChannel.bind(new InetSocketAddress(9999));// 5. 将通道注册到选择器socketChannel.register(selector, SelectionKey.OP_ACCEPT);

上面通过调用通道的 register() 方法会将它注册到一个选择器上。

需要注意的是:

(1)与 Selector 一起使用, channel 必须处于非阻塞模式下,否则将抛出异常 IllegalBlockingModeException 。 这意味着,FileChannel 不能与 Selector 一起使用,因为 FileChannel 不能切换到非阻塞模式,而套接字相关的所有通道都可以。

(2)一个通道,并没有一定要持有所有的四种操作。比如服务器通道 ServerSocketChannel 支持 Accept 接收操作,而 SocketChannel 客户端通道则不支持。可以通过通道上的 vildOps() 方法,来获取特定通道下所支持的操作集合。

3、轮训查询就绪操作

(1) 通过 Selector 的 select() 方法, 可以查询出已经就绪的通道操作,有些就绪的状态集合,包含在一个元素是 Selectionkey 对象的 Set 集合中

(2) 下面是 Selector 几个重载的查询 select() 方法:

  1. select() 阻塞到至少有一个通道在你注册的事件上就绪。

  2. select(long timeout) select() 一样,但最长阻塞事件为 timeout 毫秒。

  3. selectNow() 非阻塞,只要有通道就立即返回。

  4. select() 方法返回的 int 之,表示有多少通道已经就绪,准确的说目前一次 select

方法来到这一次 select 方法之间的时间段上,有多少个通道编程了就绪状态。

例如:首次调用 select() 方法,如果有一个通道编程了就绪状态,返回了 1 , 若子啊次调用 select() 方法,如果另外一个通道就绪了,它会再次返回 1。 如果第一个就绪的 chnanel 么有做任何操作,现在就有两个就绪通道,但是每次 select() 方法调用之间,只有一个通道就绪了。

一旦调用 select() 方法,并且返回值部位 0 时,在 Selector 中有一个 seletedKeys() 方法,用来范围已选择键集合,迭代集合的每个以元素,根据就绪操作的类型,完成对应的操作

// 查询已经就绪的通道操作Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectedKeys.iterator();while (iterator.hasNext()) {    SelectionKey key = iterator.next();    // 判断 key 就绪状态操作    if (key.isAcceptable()) {        // a connection was accepted by a ServerSocketChannel.    } else if (key.isConnectable()) {        // a connection was established with a remote server.    } else if (key.isReadable()) {        // a channel is ready for reading    } else if (key.isWritable()) {        // a channel is ready for writing    }}iterator.remove();

4、停止选择的方法

选择器执行选择的过程汇总,系统底层会依次询问每个通道是否已经就绪,这个过程可能会造成调用线程进入阻塞状态,那么我们有一下三种方式可以唤醒在 select()方法中阻塞的线程。

wakeup() 方法:通过调用 Selector 对象的 wakeup() 方法让处于阻塞状态的 select() 方法立刻返回

该方法使得选择器上的第一个哈没有返回的选择操作立即返回。如果当前没有进行中的选择操作,那么下一次会对 select() 方法的一次调用立即返回。

close() 方法: 通过 close() 方法关闭 selector

该方法使得任何一个在选择操作中阻塞的线程都被唤醒(类似 wakeup()) , 同时使的注册到该 Selector 的所有 Channel 被注销,所有的键都被取消,但是 Channel 本身不会关闭。

三、示例代码

1、服务端代码

@Testpublic void server() throws IOException {    //1. 获取服务端通道    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();    //2. 切换非阻塞模式    serverSocketChannel.configureBlocking(false);    //3. 创建 buffer    ByteBuffer readBuffer = ByteBuffer.allocate(1024);    ByteBuffer writeBuffer = ByteBuffer.allocate(1024);    writeBuffer.put("收到了。。。。".getBytes(StandardCharsets.UTF_8));    //4. 绑定端口号    serverSocketChannel.bind(new InetSocketAddress(20000));    //5. 获取 selector 选择器    Selector selector = Selector.open();    //6. 通道注册到选择器,进行监听    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);    //7. 选择器进行轮训,进行后续操作    while (selector.select() > 0) {        Set<SelectionKey> selectionKeys = selector.selectedKeys();        Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();        // 循环        while (selectionKeyIterator.hasNext()) {            // 获取就绪状态            SelectionKey k = selectionKeyIterator.next();            // 操作判断            if (k.isAcceptable()) {                // 获取连接                SocketChannel accept = serverSocketChannel.accept();                // 切换非阻塞模式                accept.configureBlocking(false);                // 注册                accept.register(selector, SelectionKey.OP_READ);            } else if (k.isReadable()) {                SocketChannel socketChannel = (SocketChannel) k.channel();                readBuffer.clear();                socketChannel.read(readBuffer);                readBuffer.flip();                System.out.println("received:" + new String(readBuffer.array(), StandardCharsets.UTF_8));                k.interestOps(SelectionKey.OP_WRITE);            } else if (k.isWritable()) {                writeBuffer.rewind();                SocketChannel socketChannel = (SocketChannel) k.channel();                socketChannel.write(writeBuffer);                k.interestOps(SelectionKey.OP_READ);            }        }    }}

2、客户端代码

@Testpublic void client() throws IOException {    //1. 获取通道,绑定主机和端口号    SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(20000));    //2. 切换到非阻塞模式    socketChannel.configureBlocking(false);    //3. 创建 buffer    ByteBuffer buffer = ByteBuffer.allocate(1024);    //4. 写入 buffer 数据    buffer.put(new Date().toString().getBytes(StandardCharsets.UTF_8));    //5. 模式切换    buffer.flip();    //6. 写入通道    socketChannel.write(buffer);    //7. 关闭    buffer.clear();    socketChannel.close();}

3、NIO 编程步骤总结

  • 1、创建一个 ServerSocketChannel 通道

  • 2、设置为非阻塞模式

  • 3、创建一个 Selector 选择器

  • 4、Channel 注册到选择器中,监听连接事件

  • 5、调用 Selector 中的 select 方法(循环调用),监听通道是否是就绪状态

  • 6、调用 SelectKeys() 方法就能获取 就绪 channel 集合

  • 7、遍历就绪的 channel 集合,判断就绪事件类型,实现具体的业务操作。

  • 8、根据业务流程,判断是否需要再次注册事件监听事件,重复执行。

关于“Java NIO中Selector是什么”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

--结束END--

本文标题: Java NIO中Selector是什么

本文链接: https://lsjlt.com/news/322125.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java NIO中Selector是什么
    这篇文章将为大家详细讲解有关Java NIO中Selector是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、Selector 简介1、Selector 和 Channel 关系Sele...
    99+
    2023-06-29
  • Java NIO类库Selector机制是什么
    这篇文章主要介绍“Java NIO类库Selector机制是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java NIO类库Selector机制是什么”文章能帮助大家解决问题。迷惑不解 : 为...
    99+
    2023-06-17
  • Java NIO 中 Selector 解析
    目录一、Selector 简介1、Selector 和 Channel 关系2、可选择通道(SelectableChannel)3、Channel 注册到 Selector4、选择键...
    99+
    2024-04-02
  • java中什么是Selector
    这篇文章给大家介绍java中什么是Selector,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。常用的java框架有哪些1.SpringMVC,Spring Web MVC是一种基于Java的实现了Web MVC设计模...
    99+
    2023-06-14
  • java中是什么是NIO
    java中是什么是NIO?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。常用的java框架有哪些1.SpringMVC,Spring Web MVC是一种基于Java的实现了...
    99+
    2023-06-14
  • Java NIO类库Selector机制的原理
    本篇内容主要讲解“Java NIO类库Selector机制的原理”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java NIO类库Selector机制的原理”吧! 一、  前...
    99+
    2023-06-17
  • Java的NIO是什么
    Java提供了一个叫作NIO(New I/O)的第二个I/O系统,NIO提供了与标准I/O API不同的I/O处理方式。它是Java用来替代传统I/O API(自Java 1.4以来)。 (推荐学习:java课程)它支持...
    99+
    2018-06-12
    java教程 Java
  • Java网络编程与NIO详解4:浅析NIO包中的Buffer、Channel 和 Selector
    本文转载自互联网本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看https://github.com/h3pl/Java-Tutorial喜欢的话麻烦点下Star哈文章将同步到我的个人博客:ww...
    99+
    2023-06-02
  • Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理
    本文转自互联网本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看https://github.com/h3pl/Java-Tutorial喜欢的话麻烦点下Star哈文章将同步到我的个人博客:www...
    99+
    2023-06-02
  • css中selector是什么意思
    这篇文章给大家分享的是有关css中selector是什么意思的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 选择器 (selector) 通常是你希...
    99+
    2024-04-02
  • Java NIO底层原理是什么
    这篇文章主要介绍“Java NIO底层原理是什么”,在日常操作中,相信很多人在Java NIO底层原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java NIO底层原理是什么”的疑惑有所帮助!接下来...
    99+
    2023-06-16
  • Java中BIO、NIO和AIO的区别是什么
    这篇文章主要讲解了“Java中BIO、NIO和AIO的区别是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中BIO、NIO和AIO的区别是什么”吧!IO什么是IO 它是指计算机与...
    99+
    2023-06-22
  • Android中selector的作用是什么
    在Android中,selector的作用是为View提供不同的状态下的不同视觉表现。它是一个XML文件,用于定义不同状态下的背景、...
    99+
    2023-10-18
    Android
  • kubernetes中Label和Label Selector是什么
    小编给大家分享一下kubernetes中Label和Label Selector是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一:什么是Label...
    99+
    2023-06-04
  • Android中selector的用法是什么
    在Android中,selector是一个XML文件,用于定义不同状态下的视图样式。它可以被应用于按钮、背景、文本颜色等视图元素,以...
    99+
    2024-02-29
    Android selector
  • Java NIO是什么及怎么使用
    Java NIO(New IO)是Java 1.4版本中引入的一种用于替代传统Java IO的新的输入输出API。NIO提供了更高效...
    99+
    2023-09-27
    Java
  • Java NIO Buffer实现原理是什么
    本篇内容介绍了“Java NIO Buffer实现原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、Buffe...
    99+
    2023-06-21
  • Java IO模型中的BIO,NIO和AIO是什么
    本篇内容主要讲解“Java IO模型中的BIO,NIO和AIO是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java IO模型中的BIO,NIO和AIO是什么”吧!一、I/O模型1.1 I...
    99+
    2023-06-29
  • Java NIO Socket通信的方法是什么
    这篇文章主要讲解了“Java NIO Socket通信的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java NIO Socket通信的方法是什么”吧!服务器代码:import&...
    99+
    2023-06-17
  • Java NIO的ByteBuffer工作原理是什么
    这篇文章给大家介绍Java NIO的ByteBuffer工作原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1 APINetty 的数据处理 API 通过两个组件暴露——抽象类ByteBuf 和 接口 Byte...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作