有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准
https://blog.zysicyj.top
全网最细面试题手册,支持艾宾浩斯记忆法。这是一份最全面、最详细、最高质量的 java面试题,不建议你死记硬背,只要每天复习一遍,有个大概印象就行了。 https://store.amazingmemo.com/chapterDetail/1685324709017001`

NIO下的Reactor多线程模型
在Java NIO中,Reactor模式是一种用于处理并发网络连接的设计模式。它允许系统以非阻塞的方式处理多个客户端连接,这是通过单个或多个输入输出线程来实现的。在多线程Reactor模型中,可以有多个Reactor来处理不同的任务,如连接接受、读/写处理等。
基本概念
在深入了解Reactor多线程模型之前,我们需要理解以下几个关键概念:
- Selector(选择器):一个Selector可以检测多个注册的通道上是否有事件发生,如果有事件发生,便获取事件然后进行相应的处理。
- Channel(通道):类似于流,但主要区别在于它可以进行非阻塞的读写。
- Buffer(缓冲区):数据的容器,Channel读写数据都是通过Buffer进行的。
Reactor多线程模型
在Reactor多线程模型中,通常包含以下几个组件:
- Main Reactor:负责处理客户端的连接请求。
- Sub Reactor:负责处理非阻塞的读/写事件。
- Worker Pool:一组工作线程,用于执行耗时操作,如业务处理、数据库操作等。
工作流程
Main Reactor线程:当客户端发起连接请求时,Main Reactor通过Selector监听ACCEPT事件。一旦ACCEPT事件到达,Main Reactor将处理连接请求,创建一个新的SocketChannel,并将其注册到Sub Reactor的Selector上,监听READ或WRITE事件。
Sub Reactor线程:Sub Reactor继续监听已连接的SocketChannel上的READ或WRITE事件。当这些事件发生时,Sub Reactor将相应的Channel分配给一个线程(通常来自线程池)进行非阻塞的读写操作。
Worker Pool线程:一旦读写操作完成,Worker Pool中的线程可以进行进一步的处理,如业务逻辑处理或数据库操作。处理完成后,结果可以返回给Sub Reactor线程,由它来完成数据的最终发送。
优点
- 高效的资源利用:由于使用非阻塞IO,线程可以在没有IO操作时处理其他任务,提高资源利用率。
- 可扩展性:可以通过增加更多的Sub Reactor线程来处理更多的并发连接,从而提高系统的可扩展性。
- 快速响应:Reactor模式可以快速响应网络事件,提高系统的响应能力。
缺点
- 复杂性:相比传统的阻塞IO模型,Reactor模式在实现上更为复杂。
- 调试难度:由于涉及多线程和非阻塞IO,调试可能会更加困难。
示例代码
下面是一个简化的Reactor多线程模型的Java代码示例:
public class Reactor implements Runnable {
final Selector selector;
final ServerSocketChannel serverSocketChannel;
Reactor(int port) throws IOException {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(port));
serverSocketChannel.configureBlocking(false);
SelectionKey sk = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
sk.attach(new Acceptor());
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
selector.select();
Set<SelectionKey> selected = selector.selectedKeys();
Iterator<SelectionKey> it = selected.iterator();
while (it.hasNext()) {
dispatch(it.next());
it.remove();
}
}
} catch (IOException ex) {
// Handle exception
}
}
void dispatch(SelectionKey k) {
Runnable r = (Runnable) (k.attachment());
if (r != null) {
r.run();
}
}
class Acceptor implements Runnable {
@Override
public void run() {
try {
SocketChannel c = serverSocketChannel.accept();
if (c != null) {
new Handler(selector, c);
}
} catch (IOException ex) {
// Handle exception
}
}
}
}
在这个示例中,Reactor类负责初始化Selector和ServerSocketChannel,并在运行时处理ACCEPT事件。Acceptor类负责接受新的连接请求。Handler类(未展示)将处理READ和WRITE事件,并可能将任务委托给Worker Pool线程。
请注意,这只是一个非常简化的示例,实际应用中的Reactor模式实现会更加复杂,涉及更多的错误处理和资源管理。


