selector与channel绑定须先调用configureblocking(false),仅socketchannel、serversocketchannel和datagramchannel支持;注册本质是向操作系统多路复用器提交fd及事件兴趣集,selector通过selectionkey管理,支持动态修改兴趣集或cancel()取消绑定;select()后需遍历selectedkeys()并手动remove()键。

Selector与Channel绑定的前提条件
绑定必须在Channel处于非阻塞模式下进行。调用configureBlocking(false)是强制步骤,否则注册时会抛出IllegalBlockingModeException。FileChannel不能参与绑定,因为它不继承SelectableChannel,也不支持非阻塞模式;只有SocketChannel、ServerSocketChannel和DatagramChannel这类可选择通道才适用。
注册过程的本质是事件兴趣集设定
调用channel.register(selector, ops)时,并非建立“硬连接”,而是将该Channel的文件描述符(fd)及其关注的操作类型(如OP_READ、OP_ACCEPT)提交给底层操作系统多路复用器(Linux下为epoll,macOS下为kqueue)。Selector内部维护一个键集合(SelectionKey),每个键封装了Channel、事件兴趣集、就绪操作集以及附加对象(可选)。
- 一个Channel可以注册到多个Selector,但同一Selector中只能注册一次
- 注册后可通过
key.channel()反查通道,通过key.interestOps()查看当前关注事件 - 兴趣集支持位运算组合,例如
OP_READ | OP_WRITE
动态更新兴趣集与取消绑定
绑定不是一成不变的。运行中可随时修改关注事件或彻底解绑:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 修改兴趣集:获取已注册的
SelectionKey,调用key.interestOps(newOps) - 临时禁用某类事件:用位与操作清除对应标志,如
key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE) - 主动取消绑定:调用
key.cancel(),该键将在下一次select()后从selectedKeys()中移除,并最终被清理
就绪事件驱动的实际响应逻辑
Selector本身不主动触发I/O,它只做状态通知。每次调用select()后,需遍历selectedKeys()检查哪些Channel已就绪:
-
key.isAcceptable()→ 表示ServerSocketChannel有新连接待accept -
key.isReadable()→ SocketChannel有数据可读(不会阻塞) -
key.isWritable()→ SocketChannel缓冲区有空间可写(通常总是就绪,需谨慎使用) -
key.isConnectable()→ 客户端SocketChannel完成TCP三次握手
处理完每个键后,务必调用iterator.remove()或keys.clear(),否则该键会在下次select中重复出现。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










