NIO SelectionKey 详解

SelectionKey 是 Java NIO 中的一个重要类,用于表示一个通道在 Selector 上的注册关系。它包含了通道的状态信息和感兴趣的事件类型。SelectionKey 是使用 Selector 时的核心组件之一,因为它帮助管理和识别通道的 I/O事件。

SelectionKey 的基本概念

  • 通道(Channel) :代表一个可以进行 I/O 操作的实体,如 SocketChannelServerSocketChannel 等。
  • 选择器(Selector):用于监视多个通道上的 I/O事件。
  • 选择键(SelectionKey) :表示一个通道在 Selector 上的注册,包含该通道的事件兴趣和状态。

SelectionKey 的常量

SelectionKey 使用了一些常量来表示通道的不同事件类型:

  • OP_READ:表示通道中有数据可读。
  • OP_WRITE:表示通道可以写数据。
  • OP_CONNECT:表示连接操作已经完成。
  • OP_ACCEPT:表示服务器通道已准备好接受新的连接。

这些常量是位掩码,可以组合使用。例如,OP_READ | OP_WRITE 表示对读和写事件都感兴趣。

SelectionKey 的主要方法

  1. interestOps()

    java 复制代码
    int interestSet = selectionKey.interestOps();

    返回当前选择键的兴趣集,即通道感兴趣的操作。

  2. interestOps(int ops)

    java 复制代码
    selectionKey.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);

    设置通道的兴趣集,指定对哪些操作感兴趣。

  3. readyOps()

    java 复制代码
    int readySet = selectionKey.readyOps();

    返回通道已经准备好的操作集。

  4. channel()

    java 复制代码
    SelectableChannel channel = selectionKey.channel();

    返回与此选择键关联的通道。

  5. selector()

    java 复制代码
    Selector selector = selectionKey.selector();

    返回生成此选择键的选择器。

  6. isValid()

    java 复制代码
    boolean valid = selectionKey.isValid();

    检查选择键是否仍然有效。

  7. cancel()

    java 复制代码
    selectionKey.cancel();

    取消选择键,使其无效。

  8. attach(Object obj)attachment()

    java 复制代码
    selectionKey.attach(someObject);
    Object attached = selectionKey.attachment();

    可以将一个对象附加到选择键上,便于在处理事件时访问相关数据。

使用 SelectionKey

在使用 Selector 进行非阻塞 I/O 操作时,SelectionKey 用于识别哪些通道已经准备好进行 I/O 操作,并获取相关的通道和附加信息。

示例

以下是一个简单的使用 SelectionKey 的示例:

java 复制代码
Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8080));
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);

while (true) {
    selector.select();
    Set<SelectionKey> selectedKeys = selector.selectedKeys();
    Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

    while (keyIterator.hasNext()) {
        SelectionKey key = keyIterator.next();

        if (key.isAcceptable()) {
            ServerSocketChannel server = (ServerSocketChannel) key.channel();
            SocketChannel client = server.accept();
            client.configureBlocking(false);
            client.register(selector, SelectionKey.OP_READ);
        } else if (key.isReadable()) {
            SocketChannel client = (SocketChannel) key.channel();
            ByteBuffer buffer = ByteBuffer.allocate(256);
            client.read(buffer);
            // 处理读取的数据
        }

        keyIterator.remove();
    }
}

注意事项

  • 有效性 :在处理完一个 SelectionKey 后,通常需要调用 keyIterator.remove() 来从集合中移除它,以避免重复处理。
  • 附加对象 :可以通过 attach()attachment() 方法将上下文信息附加到选择键上,方便在事件处理时使用。
  • 取消键 :当通道不再需要时,可以调用 cancel() 方法取消选择键。

SelectionKey 是 Java NIO 中实现高效非阻塞 I/O 操作的关键工具之一,通过它可以有效地管理和处理多个通道的事件。

参考

NIO Selector 详解

相关推荐
上进小菜猪10 分钟前
把 KES 集群交给 Kubernetes 的九十天:一个 DBA 的试用实录
后端
两点王爷1 小时前
PostgreSQL 常用 SQL 语句与 GIS 相关函数详解
数据库·后端
考虑考虑1 小时前
Springboot环境变量占位符语法
spring boot·后端·spring
步行cgn3 小时前
Spring 基于 XML 的自动装配:byName 详解
java·后端·spring
RISCV_Explorer5 小时前
RISC-V启动与运行时规范机制解析——BRS约定、HSM多核启动与设备树要求
后端·risc-v
星栈独行5 小时前
ADK-Rust 是什么?Rust 生态新一代 AI Agent 开发套件
人工智能·后端·rust
JavaGuide5 小时前
对标 MinIO!全新一代分布式文件系统正式发布
前端·后端
用户8356290780516 小时前
使用 Python 将 DOCX 转换为 Markdown
后端·python
IT_陈寒6 小时前
Vue computed属性这个坑,我居然踩了三次才爬出来
前端·人工智能·后端
孙启超7 小时前
【AI开发之Rust】第 7 课:错误处理 —— panic、Result 与 `?`
人工智能·分布式·后端·爬虫·spring cloud·架构·rust