Java NIO基于Reactor模型构建网络服务器,核心是Selector事件多路复用,配合非阻塞Channel与ByteBuffer管理;含Reactor(事件监听分发)、Handler(连接级业务处理)和Channel+Buffer(I/O操作载体)三角色;单Reactor单线程适合入门,单Reactor多线程将业务逻辑交由线程池,主从Reactor多线程则由BossGroup处理accept、WorkerGroup分担读写,支撑高并发。

Java NIO 实现基于 Reactor 模型的网络服务器,核心是用 Selector 做事件多路复用,把连接、读、写等 I/O 事件的监听和分发交给一个或多个反应器(Reactor)线程,再配合非阻塞 Channel 和缓冲区管理,避免线程阻塞在单个连接上。
关键角色要分清
Reactor 模型里有三个基础角色:
-
Reactor(反应器):负责调用
selector.select()监听就绪事件,并把事件分发给对应处理器。它不处理业务逻辑,只做调度。 -
Handler(处理器):每个连接绑定一个 Handler(常通过
SelectionKey.attach()关联),负责具体读数据、解码、调用业务、编码、写回等。比如Acceptor处理新连接,ReadHandler处理读事件。 -
Channel + Buffer:所有 Channel 必须设为非阻塞(
configureBlocking(false)),读写使用 ByteBuffer,注意 flip/clear/compact 的时机,尤其不能假设一次read()就能读满一帧(半包问题就出在这)。
单 Reactor 单线程模型(适合入门理解)
整个流程跑在一个线程里,Selector 轮询,事件来了就 dispatch 给对应 Handler:
- 启动时打开
ServerSocketChannel,绑定端口,注册OP_ACCEPT到 Selector。 - 收到 accept 事件,调用
accept()得到SocketChannel,设为非阻塞,注册OP_READ,并 attach 一个读 Handler。 - 收到 read 事件,从 Channel 读入 ByteBuffer;必须检查是否读完一帧(比如按换行符或长度前缀解析),没读完就继续等待下次 read;不能直接
get(32)——那是典型半包陷阱。 - 写操作一般注册
OP_WRITE并 attach 写缓冲区,等 write 就绪再发,避免 write() 返回 0 时卡住。
单 Reactor 多线程模型(生产常用)
Reactor 线程只管 I/O 事件分发,把解码、业务处理、编码等 CPU 密集型任务扔给线程池:
立即学习“Java免费学习笔记(深入)”;
- 读事件触发后,Reactor 线程把接收到的原始字节(或完整帧)封装成任务,提交到业务线程池。
- 业务处理完生成响应后,通常需要由 Reactor 线程(或专门的写线程)执行
channel.write(),因为 Channel 不是线程安全的,且 write 可能未完成需注册 OP_WRITE 继续驱动。 - 这样既避免 Reactor 线程被业务阻塞,又保证 I/O 操作仍在正确的线程上下文中执行。
主从 Reactor 多线程模型(高并发场景)
一个主 Reactor 专管 accept,多个从 Reactor 分摊 read/write 负载:
- 主 Reactor 在
OP_ACCEPT就绪时接受连接,然后轮询选择一个从 Reactor,把新连接的SocketChannel注册到它的 Selector 上。 - 每个从 Reactor 独立运行 select 循环,处理自己名下的一批连接,天然隔离 I/O 负载。
- Netty 默认就是这种模型(BossGroup + WorkerGroup),可支撑数万级并发连接。


















