跳转到主内容
极星编程网:以代码为星,赴技术山海!

如何通过SelectionKey的attachment附加自定义业务对象

可通过SelectionKey.attach()绑定业务对象,事件处理时用key.attachment()取回;适用于存储会话、缓冲区等通道关联状态,应在注册后或OP_ACCEPT时绑定,避免重复attach。 可以通过
SelectionKey.attach(Object)
方法将自定义业务对象绑定到键上,后续在事件处理(如
OP_READ
、
OP_WRITE
)中通过
key.attachment()
取回,实现通道与业务上下文的关联。 attachment 的作用和适用场景 attachment 是 SelectionKey 提供的一个“挂载点”,用于存储与该通道生命周期一致的业务状态。比如:一个客户端连接对应的会话对象、请求缓冲区、协议解析器、用户身份信息等。它避免了用 Map 显式维护 channel → object 映射,也规避了并发访问 map 的同步开销。 正确设置 attachment 的时机 attachment 应在注册 Channel 到 Selector 后、首次事件触发前完成绑定,常见位置有: 调用
channel.register(selector, ops)
得到 SelectionKey 后立即 attach 在
OP_ACCEPT
事件中,为新 accept 的 SocketChannel 创建并 attach 新会话对象 不要在事件循环中反复 attach(会覆盖),除非明确需要更新上下文 典型使用示例(简化版) 假设处理客户端连接,每个连接需维护自己的读缓冲区和用户 ID:
// 接受新连接时 SocketChannel client = serverChannel.accept(); client.configureBlocking(false); SelectionKey key = client.register(selector, SelectionKey.OP_READ); // 绑定自定义会话对象 Session session = new Session(client.getRemoteAddress(), ByteBuffer.allocate(1024)); key.attach(session); // 在 OP_READ 事件中 if (key.isReadable()) { Session s = (Session) key.attachment(); // 安全取回 ByteBuffer buf = s.buffer; int n = client.read(buf); if (n > 0) { buf.flip(); // 解析业务数据,s.userId 可用于权限判断等 processRequest(buf, s.userId); } }
注意事项 类型安全 :attach 接收 Object,取回时务必强转,并建议用泛型工具类或封装 key 操作避免 ClassCastException。 线程安全 :attachment 本身不保证线程安全;若多线程可能修改同一 key 的 attachment(如同时 OP_READ 和 OP_WRITE),需自行同步或改用不可变对象。 内存泄漏风险 :确保在连接关闭时清理相关资源(如释放 ByteBuffer、关闭流),attachment 引用的对象不会自动被回收,需在
key.cancel()
前手动置空或清理。

相关文章