netty基础-NIO的selector

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了netty基础-NIO的selector相关的知识,希望对你有一定的参考价值。

参考技术A 上面是创建Selector的过程。可以看到Selector是 new KQueueSelectorProvider 生成的,然后调用open()方法,open()方法调用是 new KQueueSelectorImpl(this) 此处的this是 KQueueSelectorProvider 对象。在KQueueSelectorImpl这个类里面有几个属性。看名字应该是队列。

可以看到上面的 selector = Selector.open(); 就是实例一个 KQueueSelectorImpl

SelectionKeyImpl对象包含了ServerSocketChannel;Selector这样在使用时可以从SelectionKey里面获得Channel,进而读取Channel里面的数据

分析到这可以知道在SelectionKey里面是有Channel对象的,如果使用ServerSocketChannel进行register那么Selectionkey里面保存的就是ServerSocketChannel。如果使用SocketChannel进行register那么SelectionKey里面保存的就是SocketChannel。在回到前一篇 《netty基础-NIO简单demo》 首先是 server.register(selector, SelectionKey.OP_ACCEPT); 这是如果接收到Accept事件,那么SelectionKey里面存放的是ServerSocketChannel。然后在Accept事件中我们又绑定了read事件。这是使用的 client.register(selector,SelectionKey.OP_READ); 那么在read事件中获得的Channel就是SocketChannel

Netty——NIO(Selector)

目录

一、多路复用

  • 单线程可以配合 Selector 完成对多个 Channel 可读写事件的监控,这称之为多路复用。
  • 多路复用仅针对网络 IO、普通文件 IO 没法利用多路复用。
  • 如果不用 Selector 的非阻塞模式,线程大部分时间都在做无用功,而 Selector 能够保证
    (1)、有可连接事件时才去连接;
    (2)、有可读事件才去读取;
    (3)、有可写事件才去写入;
    (4)、限于网络传输能力,Channel 未必时时可写,一旦 Channel 可写,会触发 Selector 的可写事件;

二、Selector的概述

2.1、Selector的优点

  • 一个线程配合 selector 就可以监控多个 channel 的事件,事件发生线程才去处理。避免非阻塞模式下所做无用功;
  • 让这个线程能够被充分利用;
  • 节约了线程的数量;
  • 减少了线程上下文切换;

2.2、Selector的创建

  • Selector创建的语法

     //创建Selector,管理多个channel
     Selector selector = Selector.open();
    

2.3、Selector绑定 Channel 事件

  • Selector绑定 Channel 事件也称之为注册事件,绑定的事件 selector 才会关心。

  • Selector绑定 Channel 事件语法

    channel.configureBlocking(false); 
     /**
      * 3、建立Selector与channel的联系(也称为注册)
      * key只关注事件,绑定的事件类型4种,
      * connect - 客户端连接成功时触发;
      * accept - 服务器端成功接受连接时触发; 
      * read - 数据可读入时触发;
      * write - 数据可写出时触发,
      * */
    SelectionKey key = channel.register(selector, 绑定事件);
    

2.4、Selector监听 Channel 事件

  • 可以通过下面三种方法来监听是否有事件发生,方法的返回值代表有多少 channel 发生了事件。

  • 方法1:阻塞直到绑定事件发生

    int count = selector.select();
    
  • 方法2:阻塞直到绑定事件发生,或是超时(时间单位为 ms)

    int count = selector.select(long timeout);
    
  • 方法3:不会阻塞,也就是不管有没有事件,立刻返回,自己根据返回值检查是否有事件

    int count = selector.selectNow();
    

2.5、Selector何时不阻塞

  • 事件发生时
    (1)、客户端发起连接请求,会触发 accept 事件;
    (2)、客户端发送数据过来,客户端正常、异常关闭时,都会触发 read 事件,另外如果发送的数据大于 buffer 缓冲区,会触发多次读取事件;
    (3)、channel 可写,会触发 write 事件;
    (4)、在 linux 下 nio bug 发生时;
  • 调用 selector.wakeup()
  • 调用 selector.close()
  • selector 所在线程 interrupt

以上是关于netty基础-NIO的selector的主要内容,如果未能解决你的问题,请参考以下文章

netty基础-NIO的selector

Netty系列:基础篇 BIO-NIO-AIO

Netty基础系列 --彻底理解NIO

选择Netty作为基础通信框架 .

netty系列之:NIO和netty详解

对比Java标准NIO类库,你知道Netty是如何实现更高性能的吗?