NIO多线程优化
- 使用Boss线程来处理accepct事件
- 使用Worker线程来处理读写事件,可以创建多个worker线程
java
package com.review;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;
@Slf4j
public class MultiServer {
public static void main(String[] args) throws IOException {
Thread.currentThread().setName("BOSS");
Selector selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ssc.bind(new InetSocketAddress(11027));
SelectionKey sscKey = ssc.register(selector, 0, null);
sscKey.interestOps(SelectionKey.OP_ACCEPT);
Worker worker = new Worker("worker-0");
while (true){
selector.select();
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()){
SelectionKey key = iterator.next();
iterator.remove();
if (key.isAcceptable()){
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
SocketChannel sc = serverSocketChannel.accept();
sc.configureBlocking(false);
worker.register(sc);
worker.selector.wakeup();
}
}
}
}
static class Worker implements Runnable{
private String name;
private Selector selector;
private Thread thread;
private volatile boolean start;
ConcurrentLinkedQueue<Runnable> queue = new ConcurrentLinkedQueue<>();
public Worker(String name){
this.name = name;
}
public void register(SocketChannel sc) throws IOException {
if (!start){
selector = Selector.open();
thread = new Thread(this,this.name);
thread.start();
start = true;
}
queue.add(()->{
try {
SelectionKey scKey = sc.register(selector, 0, null);
scKey.interestOps(SelectionKey.OP_READ);
} catch (ClosedChannelException e) {
log.error(e.getMessage(),e);
}
});
}
@Override
public void run() {
while (true){
try {
selector.select();
} catch (IOException e) {
log.error(e.getMessage(),e);
}
if (queue.size() > 0){
queue.poll().run();
}
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
iterator.remove();
if (selectionKey.isReadable()){
SocketChannel channel = (SocketChannel) selectionKey.channel();
}
}
}
}
}
}
------------本专栏来自于对满叔在b站所讲的netty课程的理解