NioEventLoopGroup-的创建过程

263 阅读2分钟

一:我们先来看一下他的创建过程

继承实现关系图 image.png

EventLoopGroup group = new NioEventLoopGroup();

通过上边的继承图可以看出,昨天使用EventLoopGroup来进行接收NioEventLoopGroup组来进行创建该对象;

public NioEventLoopGroup() {
    this(0);
}

public NioEventLoopGroup(int nThreads) {
    this(nThreads, (Executor) null);
}

public NioEventLoopGroup(int nThreads, Executor executor) {
    this(nThreads, executor, SelectorProvider.provider());
}

接下来可以看到,如果不传入初始线程数量,那么默认这传递的是0,和一个选择提供者

public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
                         final SelectStrategyFactory selectStrategyFactory) {
    super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}

最后这里就是在NioEventLoopGroup里面最后的增加就是增加了一个拒绝策略,接下来就会到其父类,也就是 MultithreadEventLoopGroup 进行数据初始化

protected MultithreadEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory,
                                 Object... args) {
    super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, chooserFactory, args);
}

static {
    DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
            "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));

    if (logger.isDebugEnabled()) {
        logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
    }
}

可以查看此方法对之前的nThreads进行了判断,如果传入为0那么久在1和cpu核心*2 之中取一个最大的数量

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

接下来又到了其父类MultithreadEventExecutorGroup~ 定义了一个默认执行选择器工场

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                        EventExecutorChooserFactory chooserFactory, Object... args) {
    //判断线程核心~
    checkPositive(nThreads, "nThreads");

    if (executor == null) {
        //线程前置任务执行器 传入线程工厂,返回线程工厂 因为都是 ThreadPerTaskExecutor 实现了Executor 这里只是初始化了 ThreadPerTaskExecutor里面的线程工场
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }

    //创建事件执行器,根据线程
    children = new EventExecutor[nThreads];

    //初始事件执行器
    for (int i = 0; i < nThreads; i ++) {
        boolean success = false;
        try {
            //这里传入的executor 是线程前置任务执行器  args 是选择器选择其工厂拒绝策略
            //这里此时此刻返回的是NioEventLoop  初始化了arg参数和Executor 为EventLoop 所以此时Children 就是事件执行组
            children[i] = newChild(executor, 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);
        } finally {
            //正常时不会走到这里的  一些停止和中断策略
            if (!success) {
                for (int j = 0; j < i; j ++) {
                    children[j].shutdownGracefully();
                }

                for (int j = 0; j < i; j ++) {
                    EventExecutor e = children[j];
                    try {
                        while (!e.isTerminated()) {
                            e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
                        }
                    } catch (InterruptedException interrupted) {
                        // Let the caller handle the interruption.
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
    }

    //事件执行器选择工场, 传入EventLoop[] 或者说Executor[]  然后将其多线程事件执行组的选择器进行初始化
    //这个其实就是拿是否是2的倍数来进行判断的工场方法,然后两个选择一个 来进行创建选择器
    chooser = chooserFactory.newChooser(children);

    final FutureListener<Object> terminationListener = new FutureListener<Object>() {
        @Override
        public void operationComplete(Future<Object> future) throws Exception {
            if (terminatedChildren.incrementAndGet() == children.length) {
                terminationFuture.setSuccess(null);
            }
        }
    };

    //给事件执行器添加终止监听器
    for (EventExecutor e: children) {
        e.terminationFuture().addListener(terminationListener);
    }

    Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
    Collections.addAll(childrenSet, children);
    //初始化只读事件执行器
    readonlyChildren = Collections.unmodifiableSet(childrenSet);
}

这里其实就是真正初始化NioEventLoopGroup的地方了,这里创建了事件执行器,然后又将EventLoop赋值给时间执行器数组,然后又通过children创建选择器,然后在children添加终止操作,最后返回只读EventLoop