netty-server之NioEventLoopGroup初始化(一)

1.NioEventLoopGroup的继承体系图

可以看到EventExecutorGroup是继承自ScheduleExecutorService 和 Iterable

这就意味着存在线程池和迭代器,那么NioEventLoopGroup是对线程池做了什么,迭代器又在迭代什么?往下瞅瞅~
在这里插入图片描述



2. EventExecutorGroup 核心接口功能描述

EventExecutorGroup作为核心接口,定义了基本的核心功能。那么它是干啥的呢?

官方解释:

EventExecutorGroup负责通过自己的next()方法对外提供EventExecutor。而且它也负责处理这些EventExecutor的生命周期,并对外提供全局关闭接口

从下面的方法中可以看到,EventExecutorGroup本身是具备线程池的功能的,然后内部还维护者一个EventExecutor的集合。
EventExecutor本身又是继承自EventExecutorGroup的
那么可想而知,EventExecutorGroup 就是一个线程池套一组线程池的线程池组管理工具

方法:

/**
* 检查所有被EventExecutorGroup管理的EventExecutor是否已经优雅的关闭了。
 *  全部关闭才是true	 
*/
boolean isShuttingDown();

/**
 * 基于默认值的 {shutdownGracefully(long, long, TimeUnit)}方法的简单调用方式
 */
Future<?> shutdownGracefully();

/**
 *告知executor需要进行关闭,一旦这个方法调用了,那么isShuttingDown() 方法开始返回true,而executor也准备开始关闭自己。
   * 不像shutdown()方法,这个会更优雅一点。它会有个关闭的静默期,如果在这期间有任务被提交,那么静默期就会重新计算。
   * 总的来说就是:
   * 在进行关闭前会等待一定时间,如果在这个期间有任务被提交,那么等待时间将重新开始计算
 */
Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit);

/**
 * 所有被当前EventExecutorGroup管理的EventExecutor都进行关闭后会进行异步回调
 */
Future<?> terminationFuture();

/**
 * 这个是强行关闭,已经不建议使用了
 */
@Override
@Deprecated
void shutdown();

/**
 * 这个是强行关闭,已经不建议使用了
 * 
 */
@Override
@Deprecated
List<Runnable> shutdownNow();

/**
 * (重要方法)
 *返回EventExecutorGroup管理的诸多EventExecutor中的一个,这个由子类自己决定选择方式
 */
EventExecutor next();

/**
 * =================================================
 * 下面都是ScheduledExecutorService, Iterable<EventExecutor>的方法的重写(嗯,寂寞重写)
 * =================================================
 */

@Override
Iterator<EventExecutor> iterator();

@Override
Future<?> submit(Runnable task);

@Override
<T> Future<T> submit(Runnable task, T result);

@Override
<T> Future<T> submit(Callable<T> task);

@Override
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);

@Override
<V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);

@Override
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);

@Override
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);




3.NioEventLoopGroup的初始化

它这个初始化,弯拐的比较多。其中涉及到几个默认参数值得思考。

它这里经过多层构造方法调用,然后进入父类构造MultithreadEventLoopGroup中,在这里再次进行多次构造方法调用。

这里涉及到几个构造组件:

Executor : new ThreadPerTaskExecutor(newDefaultThreadFactory())

SelectorProvider: 默认为SelectorProvider.provider()

Selector.select()轮询处理策略:DefaultSelectStrategyFactory.INSTANCE

线程池队列已满策略:RejectedExecutionHandlers.reject()

EventExecutor选择器:DefaultEventExecutorChooserFactory.INSTANCE


3.1那么NioEventLoopGroup默认的线程数是多少呢?

io.netty.channel.MultithreadEventLoopGroup

private static final int DEFAULT_EVENT_LOOP_THREADS;

static {
		// 默认为cpu处理器核数*2
    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);
    }
}

3.2 核心初始化

下面这段代码主要干了两件事:

初始化自己的EventExecutor线程池集合(EventExecutor[] children

初始化了NioEventLoopGroup对EventExecutor集合的选择器(EventExecutorChooserFactory.EventExecutorChooser

对了,还构建了一个只读集合,暂时不知道干啥用,还有看到再补充

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
        // 检查nThreads是不是正数,默认是cpu核心数*2
        checkPositive(nThreads, "nThreads");
        // 如果自己不需要定制化线程池的,有默认的单线程线程池
        if (executor == null) {
            // 线程池初始化,没有任务队列
            // newDefaultThreadFactory 负责线程的创建
            // FastThreadLocalThread
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }
        // 创建线程池组
        children = new EventExecutor[nThreads];

        for (int i = 0; i < nThreads; i ++) {
            boolean success = false;
            try {
                // 创建 NioEventLoop作为线程池组管理的元素
                children[i] = newChild(executor, args);
                success = true;
            } catch (Exception e) {
                // TODO: Think about if this is a good exception type   EventExecutorInitializeException 如何?
                throw new IllegalStateException("failed to create a child event loop", e);
            } finally {
                if (!success) {
                    for (int j = 0; j < i; j ++) {
                        // 这里 j<i 很灵性,只需要关闭异常前创建的NioEventLoop
                        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;
                        }
                    }
                }
            }
        }

        // EventExecutor 选择器,就是有请求来了,NioEventLoopGroup如何去选择EventExecutor去执行请求
        chooser = chooserFactory.newChooser(children);
        // 终止监听器,监听EventExecutor是否停掉
        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);
        // 只读EventExecutor集合
        readonlyChildren = Collections.unmodifiableSet(childrenSet);
    }


4.小结

从NioEventLoopGroup的初始化可以看到,其实它就是用来管理一系列的EventExecutor的。

下图是NioEventLoopGroup的基本组件结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UtXn1N9m-1627961912719)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/dca1d225-bfc5-4acc-b6d5-2372a792e8bd/Untitled.png)]

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值