Reactorシングルスレッドモデルの詳細
目次
Reactorモードの原理
1.原理の説明
1.Reactor模型是相对传统IO机构来说的,也就是NIO模型, NIO模型之所以可以优化,得益于
它是基于事件,基于异步,不像传统IO,是阻塞的,很难做架构上的改变
2.Reactor模型分为几个组件,分别是Reactor,Acceptor,Handler
3.Reactor组件负责分发事件,如果是连接,那么交给Acceptor,如果是读写事件,那么交给Handler
4.Acceptor负责处理连接事件(获取新连接,注册到Selector上,注册读写事件,绑定Handler)
5.Handler负责处理读写事件(使用channel进行读写)
リアクターの実装
package com.example.nio.netty;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
/**
* 单Reactor单线程模型
*/
class ReactorModel1 {
private Reactor reactor;
private Integer port;
public ReactorModel1(Integer port) throws IOException {
this.port = port;
this.reactor=new Reactor(port);
}
public void start(){
Thread thread = new Thread(this.reactor);
thread.start();
}
}
/**
* 组件Reactor(事件分发)
*/
class Reactor implements Runnable{
/**
* 端口
*/
private Integer prot;
/**
* 用于接受连接的ServerChannel
*/
private ServerSocketChannel serverSocketChannel;
/**
* 管理连接的选择器
*/
private Selector selector;
public Reactor(Integer prot) throws IOException {
this.prot = prot;
this.serverSocketChannel = ServerSocketChannel.open();
this.selector = Selector.open();
//绑定端口
this.serverSocketChannel.bind(new InetSocketAddress(prot));
//设置为非阻塞
this.serverSocketChannel.configureBlocking(false);
//注册到选择器上面
this.serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
}
@Override
public void run() {
while (true){
try {
int select = selector.select();
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
//分发事件
dispatch(selectionKey);
iterator.remove();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 进行事件分发
* @param selectionKey
*/
private void dispatch(SelectionKey selectionKey){
if (selectionKey.isAcceptable()) {
//连接事件
new Acceptor(serverSocketChannel,selector).run();
} else{
//读写事件
new Handler(selectionKey).run();
}
}
}
/**
* accepor(处理读写)
*/
class Acceptor implements Runnable{
/**
* 用于接受连接的ServerChannel
*/
private ServerSocketChannel serverSocketChannel;
/**
* 管理连接的选择器
*/
private Selector selector;
public Acceptor(ServerSocketChannel serverSocketChannel, Selector selector) {
this.serverSocketChannel = serverSocketChannel;
this.selector = selector;
}
@Override
public void run() {
//serverSocketChannel的连接事件
SocketChannel accept = null;
try {
accept = this.serverSocketChannel.accept();
//设置为非阻塞
accept.configureBlocking(false);
//注册到selector, 注册读写事件
accept.register(selector,SelectionKey.OP_READ | SelectionKey.OP_WRITE);
System.out.println("新连接:"+accept.getRemoteAddress());
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Handler implements Runnable{
private SelectionKey selectionKey;
public Handler(SelectionKey selectionKey) {
this.selectionKey = selectionKey;
}
@Override
public void run() {
try {
if(selectionKey.isReadable()){
//读事件处理
this.read();
}else {
//写事件处理
this.write();
}
}catch (Exception e){
}
}
/**
* 处理读事件
* @throws IOException
*/
private void read() throws IOException {
SocketChannel channel = (SocketChannel) selectionKey.channel();
ByteBuffer allocate = ByteBuffer.allocate(1024);
int read = channel.read(allocate);
if(read>0) {
System.out.println("接收到消息:" + new String(allocate.array(), 0,read));
}
}
/**
* 处理写事件
* @throws IOException
*/
private void write() throws IOException {
}
}
総括する
シングルリアクターシングルスレッドモデルはアーキテクチャー内のコンポーネントを区別しますが、Reactorはイベントの配布を担当し、Acceptorは新しい接続イベントの受信を担当し、Handleは読み取りおよび書き込みイベントの処理を担当しますが、全体として、Reactorスレッドの処理であり、失敗する傾向があります。 1つのスレッド処理も制限されます。ただし、Reactor、Acceptor、およびHandleはすべてRunnableインターフェースを実装してコンポーネントに分離します。これは、スレッドプールに基づいて無限に拡張できます。これは、NIOがイベントに基づいているという事実にも起因します(セレクターはより多くのチャネルイベント)、BIOとは異なり、ブロックされて個別に分離できないため、拡張するのは困難です。