• 6、Selector


        6、Selector

            (1)、特点

                Selector(选择器)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。即用选择器,借助单一线程,就可对数量庞大的活动I/O通道实施监控和维护。

                ①、Netty的IO线程NioEventLoop聚合了Selector(选择器,也叫多路复用器),可以同时并发处理成百上千个客户端连接。

                ②、当线程从某客户端Socket通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务。

                ③、线程通常将非阻塞IO的空闲时间用于在其他通道上执行IO操作,所以单独的线程可以管理多个输入和输出通道。

                ④、由于读写操作都是非阻塞的,这就可以充分提升IO线程的运行效率,避免由于频繁I/O阻塞导致的线程挂起。

                ⑤、一个I/O线程可以并发处理N个客户端连接和读写操作,这从根本上解决了传统同步阻塞I/O一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。

            (2)、核心方法

                ①、open()方法

                    得到一个Selector对象

                ②、selectedKeys()方法

                    从内部集合中得到所有的SelectionKey,注册到Selector上发生事件的Channel集合 

                ③、select()方法 / select(long timeout)方法(阻塞方法)

                    监控所有注册的通道,当其中有IO操作(事件发生)时,该方法返回,并将对应的SelectionKey加入到被选择的SelectionKey集合中,该方法返回这些Channel的数量。

                ④、wakeup()

                    唤醒selector,使一个还未返回的select()方法立即返回。

                ⑤、selectNow()(非阻塞)

                    执行一个立即返回的select()操作。

    1. public abstract class Selector implements Closeable {
    2. /**
    3. * 得到一个Selector对象
    4. */
    5. public static Selector open() throws IOException {return SelectorProvider.provider().openSelector();}
    6. /**
    7. * 获取所有的SelectionKey集合,代表注册在该Selector上的所有Channel的SelectionKey
    8. */
    9. public abstract Set keys();
    10. /**
    11. * 被选择的SelectionKey结合,返回此Selector的已选择键集,注册到Selector上发生事件的Channel集合
    12. */
    13. public abstract Set selectedKeys();
    14. /**
    15. * 监控所有注册的Channel,当它们中间有需要处理的IO操作时,该方法返回,并将对应的SelectionKey加入被选择的SelectionKey集合中,该方法返回这些Channel的数量
    16. */
    17. public abstract int select() throws IOException;
    18. /**
    19. * 可以设置超时时长的Select()操作
    20. */
    21. public abstract int select(long timeout) throws IOException;
    22. /**
    23. * 使一个还未返回的select()方法立即返回
    24. */
    25. public abstract Selector wakeup();
    26. /**
    27. * 执行一个立即返回的select()操作,该方法不会阻塞线程
    28. */
    29. public abstract int selectNow() throws IOException;
    30. /**
    31. * 关闭连接器
    32. */
    33. public abstract void close() throws IOException;
    34. }

            (3)、SelectionKey

                ①、概述

                    SelectionKey为选择键,表示SelectableChannel和Selector之间的注册关系,每次向选择器注册通道时就会选一个事件(选择键)。选择键包含两个表示为整数值的操作集。操作集的每一位都表示该键的通道所支持的一类可选择操作。

                ②、register(Selector sel, int ops):sel为Selector;ops为SelectionKey

                    若注册时不止监听一个事件(选择键),则可以使用“位或”操作符连接。

                    例:int ops = SelectionKey.OP_READ|SelectionKey.OP_WRITE;

                ③、源码解析

    1. public abstract class SelectionKey {
    2. /**
    3. * 读操作:OP_READ = 1
    4. */
    5. public static final int OP_READ = 1 << 0;
    6. /**
    7. * 写操作:OP_READ = 4
    8. */
    9. public static final int OP_WRITE = 1 << 2;
    10. /**
    11. * 连接操作:OP_READ = 8
    12. */
    13. public static final int OP_CONNECT = 1 << 3;
    14. /**
    15. * 接收操作:OP_READ = 16
    16. */
    17. public static final int OP_ACCEPT = 1 << 4;
    18. /**
    19. * 得到与之关联的channel
    20. */
    21. public abstract SelectableChannel channel();
    22. /**
    23. * 得到与之关联的Selector对象
    24. */
    25. public abstract Selector selector();
    26. /**
    27. * 得到与之关联的共享数据
    28. */
    29. public final Object attachment() {return attachment;}
    30. /**
    31. * 设置或改变监听事件,并返回SelectionKey对象
    32. */
    33. public abstract SelectionKey interestOps();
    34. /**
    35. * 获取通道已经准备就绪的操作的集合
    36. */
    37. public abstract int readyOps();
    38. /**
    39. * 检测Channel中读事件是否就绪
    40. */
    41. public final boolean isReadable() {
    42. return (readyOps() & OP_READ) != 0;
    43. }
    44. /**
    45. * 检测Channel中写事件是否就绪
    46. */
    47. public final boolean isWritable() {
    48. return (readyOps() & OP_WRITE) != 0;
    49. }
    50. /**
    51. * 检测Channel中连接是否就绪
    52. */
    53. public final boolean isConnectable() {
    54. return (readyOps() & OP_CONNECT) != 0;
    55. }
    56. /**
    57. * 检测Channel中接收是否就绪
    58. */
    59. public final boolean isAcceptable() { return (readyOps() & OP_ACCEPT) != 0; }
    60. }

  • 相关阅读:
    跟着李老师学线代——矩阵(持续更新)
    【Vue】用Vue代码详细介绍computed计算属性的用法
    什么是内容运营?
    安卓常见设计模式7------适配器模式(Kotlin版)(RecycleView adapter 模板代码)
    【OAuth2】三、OAuth2配置解读
    数字孪生北京故宫,元宇宙推进旅游业进程
    【LeetCode-简单题】383. 赎金信
    建筑楼宇VR火灾扑灭救援虚拟仿真软件厂家
    Linux网络管理OSI和TCP/IP
    华为云云耀云服务器L实例评测|基于宝塔部署SpringBoot后端+前端工程
  • 原文地址:https://blog.csdn.net/L_D_Y_K/article/details/126519062