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 详解

相关推荐
Cosolar19 小时前
AI Agent 的记忆战争:OpenClaw vs Hermes vs QwenPaw vs HiClaw,谁真正"记得住"?
人工智能·后端·面试
M ? A19 小时前
VuReact:Vue转React的增量编译利器
前端·vue.js·后端·react.js·面试·开源·vureact
aircrushin19 小时前
给宝宝办了个宴,朋友用trae做的工具帮了大忙
前端·后端
码上小翔哥19 小时前
Jackson 配置深度解析
java·后端
程序员Sunday19 小时前
爆肝万字!这应该是全网最全的 Codex 实战教程了
前端·后端·ai编程
aircrushin19 小时前
朋友用trae搭建的工具,解决了旅行拍照共享的大事儿
前端·后端
星栈19 小时前
把业务逻辑写成纯函数之后,我再也不想写 Service 层了
后端·开源
未秃头的程序猿19 小时前
如何用 AI 写出符合规范的 Java 代码?我总结了 7 条有效建议
java·后端·ai编程
阿聪谈架构19 小时前
第10章:Agent 记忆系统 —— 让 AI 真正"记住"你
人工智能·后端
木雷坞19 小时前
我把 AI Coding Agent 的 MCP 工具链放进容器里跑了一遍
后端