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

相关推荐
疯一样的码农39 分钟前
基于Spring Boot + Vue3实现的在线汽车保养维修预约管理系统源码+文档
spring boot·后端·汽车
骑着王八撵玉兔1 小时前
【持续集成与持续部署(CI/CD)工具 - Jenkins】详解
java·spring boot·后端·spring·servlet·ci/cd·jenkins
海风极客2 小时前
文件传输工具FTransferor<优化篇>
开发语言·后端·golang·编程思维
ss2732 小时前
SSM 进销存系统
java·后端
黑风风4 小时前
使用 `@Async` 实现 Spring Boot 异步编程
java·spring boot·后端
等一场春雨4 小时前
Spring Boot 3 文件下载、多文件下载以及大文件分片下载、文件流处理、批量操作 和 分片技术
java·spring boot·后端
努力的小雨4 小时前
gRPC编译与字段编号的细节探讨
后端
AI人H哥会Java4 小时前
【Spring】Spring DI(依赖注入)详解——自动装配——手动装配与自动装配的区别
java·开发语言·后端·spring·架构
GGBondlctrl5 小时前
【SpringBoot】深度解析 Spring Boot 拦截器:实现统一功能处理的关键路径
java·spring boot·后端·拦截器
计算机学姐5 小时前
基于SpringBoot+Vue的旅游推荐系统
java·vue.js·spring boot·后端·mysql·tomcat·旅游