一. 代码下载
Netty代码下载和编译参考前一篇Netty文章
https://blog.51cto.com/483181/2112163
创新互联是一家集网站建设,东源企业网站建设,东源品牌网站建设,网站定制,东源网站建设报价,网络营销,网络优化,东源网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
二. 服务器代码分析
2.1 服务器代码编写
一般Netty服务器端这样编写
    EventLoopGroup bossGroup = new NioEventLoopGroup();   //1. 实例化NioEventLoopGroup对象
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap(); //2. 
            b.group(bossGroup, workerGroup) //3. 
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 100)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new FixedLengthFrameDecoder(20));
                    }
                });
            ChannelFuture f = b.bind(port).sync(); //4.
            f.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
2.2 NioEventLoopGroup
2.2.1 NioEventLoopGroup继承关系
一步步来看,首先看第一个注释,初始化NioEventLoopGroup对象
EventLoopGroup bossGroup = new NioEventLoopGroup();   //1. 实例化NioEventLoopGroup对象
下图是NioEventLoopGroup的类继承图,包含类成员和方法,比较详细。 这个功能是IntelliJ 自带的。
右击NioEventLoopGroup类名,选择Diagrams->Show Diagram->上面有f,m的按钮,分别对应field和method。
如下:

2.2.2 NioEventLoopGroup构造函数
public NioEventLoopGroup() {
        this(0);
    }
        public NioEventLoopGroup(int nThreads) {
        this(nThreads, (Executor) null);
    }
public NioEventLoopGroup(int nThreads, Executor executor) {
        this(nThreads, executor, SelectorProvider.provider());
    }       
        public NioEventLoopGroup(
            int nThreads, Executor executor, final SelectorProvider selectorProvider) {
        this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
    }
    public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
                             final SelectStrategyFactory selectStrategyFactory) {
        super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
    }
我们可以看到几点
- NioEventLoopGroup采用的是构造函数重载的方式,以适应不同的初始化场景
 - Executor传的是null
 - SelectorProvider用的是SelectorProvider.provider()
 - 然后把构造好的参数都传给父类MultithreadEventLoopGroup (继承关系可以看上图)
 
2.2.3 SelectorProvider.provider()
private static SelectorProvider provider = null;
public static SelectorProvider provider() {
        synchronized (lock) {
            if (provider != null)
                return provider;
            return AccessController.doPrivileged(
                new PrivilegedAction() {
                    public SelectorProvider run() {
                            if (loadProviderFromProperty())
                                return provider;
                            if (loadProviderAsService())
                                return provider;
                            provider = sun.nio.ch.DefaultSelectorProvider.create();
                            return provider;
                        }
                    });
        }
    }
public class DefaultSelectorProvider {
    private DefaultSelectorProvider() {
    }
    public static SelectorProvider create() {
        return new KQueueSelectorProvider();
    }
}
public class KQueueSelectorProvider extends SelectorProviderImpl {
    public KQueueSelectorProvider() {
    }
    public AbstractSelector openSelector() throws IOException {
        return new KQueueSelectorImpl(this);
    }
}
这段代码我们也可以看到几点:
- SelectorProvider provider是一个单例,static类型
 - SelectorProvider.provider的实现,产生了一个KQueueSelectorProvider
 - KQueueSelectorProvider的openSelector会生成一个KQueueSelectorImpl
 
这个先记下来,也许后面分析会有用,继续分析MultithreadEventLoopGroup的构造函数。
2.2.4 MultithreadEventLoopGroup
protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args);
    }
private static final int DEFAULT_EVENT_LOOP_THREADS;
    static {
        DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
                "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
    }       
上面这段代码我们可以看到这几点:
- 如果我们实例化NioEventLoopGroup没有传入参数,也就是没有nThreads,那么就会采用默认的DEFAULT_EVENT_LOOP_THREADS
DEFAULT_EVENT_LOOP_THREADS如果没有配置io.netty.eventLoopThreads的话,一般是cpu核数*2 - MultithreadEventLoopGroup的实例化方法是继续调用父类的初始化方法。
 
继续父类MultithreadEventExecutorGroup
2.2.5 MultithreadEventExecutorGroup
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
        ...
        children = new EventExecutor[nThreads]; //1. 实例化children数组
        for (int i = 0; i < nThreads; i ++) { //2. 循环初始化children
            boolean success = false;
            try {
                children[i] = newChild(executor, args);
                success = true;
            } catch (Exception e) {
                throw new IllegalStateException("failed to create a child event loop", e);
            } finally {
                ...
            }
        }
        chooser = chooserFactory.newChooser(children); //3. 实例化chooser
        final FutureListener