netty源码分析(4)-注册Selector

前面几节我们分析了Channel的创建和初始化过程,都是集中在AbstractBootstrap#initAndRegister方法。在newChannel()init(channel)之后,接着的是便是注册

ChannelFuture regFuture = config().group().register(channel);

初始化的时候配置的NioEventLoopGroup,调用的是其父类MultithreadEventLoopGroupregister()

    @Override
    public ChannelFuture register(Channel channel) {
        return next().register(channel);
    }

    @Override
    public EventLoop next() {
        return (EventLoop) super.next();
    }

next()方法获取的是一个EventLoop,调用其父类MultithreadEventExecutorGroup#next()方法

    @Override
    public EventExecutor next() {
        return chooser.next();
    }

chooser是其成员变量,选择器,用于选择executors,其初始化的过程其实就是NioEventLoopGroup的初始过程,查看构造方法,一层一层往上调用,会调用到父类的父类MultithreadEventExecutorGroup#MultithreadEventExecutorGroup)

protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
        this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
    }

其中初始化了一个参数DefaultEventExecutorChooserFactory.INSTANCE实例化了一个工厂,记者看构造方法,该工厂最终初始化了chooser

public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {

//省略代码
//根据配置的线程数,创建EventExecutor数组
 children = new EventExecutor[nThreads];

//实例化数组中具体的的EventExecutor
 for (int i = 0; i < nThreads; i ++) {
  //省略代码
  children[i] = newChild(executor, args);
  //省略代码
 }

//初始化Executer选择器
chooser = chooserFactory.newChooser(children);
//省略代码
}

查看DefaultEventExecutorChooserFactory#newChooser,发现是在根据线程数创建EventExecutor的时候,返回不同的两个选择器

    public EventExecutorChooser newChooser(EventExecutor[] executors) {
        if (isPowerOfTwo(executors.length)) {
            //返回一个基于2的幂次方的选择器
            return new PowerOfTwoEventExecutorChooser(executors);
        } else {
            //返回一个通用选择器
            return new GenericEventExecutorChooser(executors);
        }
    }

不难推断其选择器的next()方法是以这个为基础返回数组中指定的EventExecutor

    private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
        private final AtomicInteger idx = new AtomicInteger();
        private final EventExecutor[] executors;

        PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

        @Override
        public EventExecutor next() {
            return executors[idx.getAndIncrement() & executors.length - 1];
        }
    }

    private static final class GenericEventExecutorChooser implements EventExecutorChooser {
        private final AtomicInteger idx = new AtomicInteger();
        private final EventExecutor[] executors;

        GenericEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

        @Override
        public EventExecutor next() {
            return executors[Math.abs(idx.getAndIncrement() % executors.length)];
        }
    }

要想知道是具体哪个EventExecutor,还得查看children[i] = newChild(executor, args);发现它是一个抽象方法,具体实现类是用户注册的NioEventLoopGroup

netty源码分析(4)-注册Selector_第1张图片

    @Override
    protected EventLoop newChild(Executor executor, Object... args) throws Exception {
        return new NioEventLoop(this, executor, (SelectorProvider) args[0],
            ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
    }

那么到这里我们发现了其实具体的EventExecutor其实是NioEventLoop,查看其register方法

    @Override
    public ChannelFuture register(Channel channel) {
        return register(new DefaultChannelPromise(channel, this));
    }

    @Override
    public ChannelFuture register(final ChannelPromise promise) {
        ObjectUtil.checkNotNull(promise, "promise");
        promise.channel().unsafe().register(this, promise);
        return promise;
    }

再进一步往下查看发现其调用的是AbstractChannel.AbstractUnsafe#register,主要干了两件事情,初始化通道的

        @Override
        public final void register(EventLoop eventLoop, final ChannelPromise promise) {
           //省略代码
            //初始化eventLoop
            AbstractChannel.this.eventLoop = eventLoop;
            
          
            if (eventLoop.inEventLoop()) {
                //eventLoop与当前线程相同直接执行
                register0(promise);
            } else {
                //eventLoop与当前线程不同则获取eventLoop的Execute再新增任务执行`register0`
                try {
                    eventLoop.execute(new Runnable() {
                        @Override
                        public void run() {
                            register0(promise);
                        }
                    });
                } 
                //省略代码
            }
        }

register0()主要做了几件事, 注册,执行Event: HandlerAdded,传递Event: ChannelRegistered,判断是否传递Event: ChannelActive

 private void register0(ChannelPromise promise) {  
                //具体的注册
                doRegister();
                
                //执行Event: HandlerAdded
                pipeline.invokeHandlerAddedIfNeeded();
                
                //传递Event: ChannelRegistered
                pipeline.fireChannelRegistered();
                
                //是否传递Event: ChannelActive
                if (isActive()) {
                    if (firstRegistration) {
                        pipeline.fireChannelActive();
                    } else if (config().isAutoRead()) {
                        beginRead();
                    }
                }

}

doRegister()是一个空方法,应当查看其具体实现AbstractNioChannel,其中,调用了java底层的时间,注册Selector并获得selectionKey

netty源码分析(4)-注册Selector_第2张图片
    @Override
    protected void doRegister() throws Exception {
        boolean selected = false;
        for (;;) {
            try {

                //注册到java的Selector,未绑定事件,并且获得selectionKey
                selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);

                return;
            } catch (CancelledKeyException e) {
                if (!selected) {
                    // Force the Selector to select now as the "canceled" SelectionKey may still be
                    // cached and not removed because no Select.select(..) operation was called yet.
                    eventLoop().selectNow();
                    selected = true;
                } else {
                    // We forced a select operation on the selector before but the SelectionKey is still cached
                    // for whatever reason. JDK bug ?
                    throw e;
                }
            }
        }
    }

你可能感兴趣的:(netty源码分析(4)-注册Selector)