netty(三):NIO——多线程优化

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课程的理解

相关推荐
桦说编程15 小时前
从 ForkJoinPool 的 Compensate 看并发框架的线程补偿思想
java·后端·源码阅读
躺平大鹅17 小时前
Java面向对象入门(类与对象,新手秒懂)
java
初次攀爬者18 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺18 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
Derek_Smart19 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
NE_STOP20 小时前
MyBatis-mybatis入门与增删改查
java
孟陬1 天前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
想用offer打牌1 天前
一站式了解四种限流算法
java·后端·go
华仔啊1 天前
Java 开发千万别给布尔变量加 is 前缀!很容易背锅
java