Netty4源码分析—NioEventLoopGroup, NioEventLoop生成Selector


    真正实现生成selector的方法是在的NioEventLoopGroup的父类MultithreadEventExecutorGroupMultithreadEventExecutorGroup(int nThreads, ThreadFactory threadFactory, Object... args)方法

参数:1nThreads为线程数量,也就是nioselector的数量,默认为CPU核数*2

    (DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt( "io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2))

    2ThreadFactory 线程工厂

    3args参数,这里的参数主要的是用于生成java nioSeletor的对象,这个参数我们没有传进去,Netty会自动判断并使用java.nio.channels.spi.SelectorProvider对象;

 

   MultithreadEventExecutorGroup方法中主要的源码:

 

if (nThreads <= 0) {
            throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
        }
        if (threadFactory == null) {
            threadFactory = newDefaultThreadFactory();
        }
        children = new SingleThreadEventExecutor[nThreads];
        for (int i = 0; i < nThreads; i ++) {
            boolean success = false;
            try {
                children[i] = newChild(threadFactory, args);
                success = true;
            } catch (Exception e) {
                // TODO: Think about if this is a good exception type
                throw new IllegalStateException("failed to create a child event loop", e);
            } 

   这段代码中最主要的是newChild(threadFactory, args)这句话主要是生成了NioEventLoop对象,NioEventLoop对象调用openSelector方法生成了nio的选择器selector

private Selector openSelector() {
        final Selector selector;
        try {
            selector = provider.openSelector();
        } catch (IOException e) {
            throw new ChannelException("failed to open a new selector", e);
        }
        if (DISABLE_KEYSET_OPTIMIZATION) {
            return selector;
        }
        try {
            SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();
            Class<?> selectorImplClass =
                    Class.forName("sun.nio.ch.SelectorImpl", false, ClassLoader.getSystemClassLoader());
            // Ensure the current selector implementation is what we can instrument.
            if (!selectorImplClass.isAssignableFrom(selector.getClass())) {
                return selector;
            }
            Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
            Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");
            selectedKeysField.setAccessible(true);
            publicSelectedKeysField.setAccessible(true);
            selectedKeysField.set(selector, selectedKeySet);
            publicSelectedKeysField.set(selector, selectedKeySet);
            selectedKeys = selectedKeySet;
            logger.trace("Instrumented an optimized java.util.Set into: {}", selector);
        } catch (Throwable t) {
            selectedKeys = null;
            logger.trace("Failed to instrument an optimized java.util.Set into: {}", selector, t);
        }

        return selector;
}

 

    其中selector = provider.openSelector()负责生成seletor,这个方法后面的操作主要是通过反射优化Set类型的selectedKeys, publicSelectedKeys,因为在selector中这两个都不是线程安全的(没看selector源码,猜测而以),Netty自己使用实现Set接口SelectedSelectionKeySet代替原来的Set实现,防止在selectedKeyspublicSelectedKeys在读写时出现java.util.ConcurrentModificationException的异常.


最后在绑定端口时,由ServerBootstrap的父类AbstractBootstrapinitAndRegiste方法调用NioEventLoopGroupregister方法将serversocketchannel注册到selector中并开始监听.

 

 

猜你喜欢

转载自bzhjian.iteye.com/blog/1971446
今日推荐