netty源码分析(三) - NioEventLoop - 1创

2020-10-08  本文已影响0人  进击的蚂蚁zzzliu

概述

创建过程主要有以下4步:

  1. 创建NioEventLoopGroup
  2. 创建ThreadPerTaskExecutor
  3. 创建NioEventLoop
  4. 创建chooser
    下面对这四个步骤进行详细解析

1. 创建NioEventLoopGroup

NioEventLoopGroup创建.png

如上图构造器的调用过程,其中重点关注几个参数的默认值

2/3/4步代码如下(忽略了非主流程代码)

protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args) {
    if (executor == null) {
        //2. 创建ThreadPerTaskExecutor
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }
    //初始化大小为nThreads数组(NioEventLoop数组)
    children = new EventExecutor[nThreads];
    for (int i = 0; i < nThreads; i ++) {
        boolean success = false;
        try {
            //3. 创建NioEventLoop
            children[i] = newChild(executor, args);
            success = true;
        } catch (Exception e) {
            throw new IllegalStateException("failed to create a child event loop", e);
        } finally {
            //忽略
        }
    }
    //4. 创建chooser
    chooser = chooserFactory.newChooser(children);
}

2. 创建ThreadPerTaskExecutor

ThreadPerTaskExecutor 每次执行任务都会创建一个线程实体; 通过ThreadFactory进行构造,然后每次execute都会创建一个线程去运行

public final class ThreadPerTaskExecutor implements Executor {
    private final ThreadFactory threadFactory;
    public ThreadPerTaskExecutor(ThreadFactory threadFactory) {
        //构造方法传入threadFactory 即 newDefaultThreadFactory()返回
        this.threadFactory = ObjectUtil.checkNotNull(threadFactory, "threadFactory");
    }
    @Override
    public void execute(Runnable command) {
        //该执行器execute时,即通过threadFactory创建一个thread,然后start
        threadFactory.newThread(command).start();
    }
}

newDefaultThreadFactory(),线程工厂,通过newThread创建线程

public DefaultThreadFactory(String poolName, boolean daemon, int priority, ThreadGroup threadGroup) {
    //默认线程名:nioEventLoopGroup-group序号(从1自增)-线程号(从0自增)
    prefix = poolName + '-' + poolId.incrementAndGet() + '-';
    //是否守护线程:false
    this.daemon = daemon;
    //优先级:10
    this.priority = priority;
    this.threadGroup = threadGroup;
}

protected Thread newThread(Runnable r, String name) {
    //创建FastThreadLocalThread
    return new FastThreadLocalThread(threadGroup, r, name);
}

3. 创建NioEventLoop

创建NioEventLoop放到数组中,新连接建立时会从数组中选取一个NioEventLoop进行绑定

NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
                 SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler,
                 EventLoopTaskQueueFactory queueFactory) {
        //newTaskQueue创建MpscQueue(一个消费者多个生产者的队列)
        super(parent, executor, false, newTaskQueue(queueFactory), newTaskQueue(queueFactory), rejectedExecutionHandler);
        //SelectorProvider.provider()
        this.provider = ObjectUtil.checkNotNull(selectorProvider, "selectorProvider");
        //DefaultSelectStrategy
        this.selectStrategy = ObjectUtil.checkNotNull(strategy, "selectStrategy");
        //调用jdk openSelector方法打开一个选择器selector
        final SelectorTuple selectorTuple = openSelector();
        this.selector = selectorTuple.selector;
        this.unwrappedSelector = selectorTuple.unwrappedSelector;
    }

4. 创建chooser

后续新连接通过该选择器找到需要绑定的NioEventLoop

public EventExecutorChooser newChooser(EventExecutor[] executors) {
    //nThread是否 2 的倍数
    if (isPowerOfTwo(executors.length)) {
        //经过优化的方式获取数组下标:idx.getAndIncrement() & executors.length - 1
        return new PowerOfTwoEventExecutorChooser(executors);
    } else {
        //普通方式获取数组下标:Math.abs(idx.getAndIncrement() % executors.length)
        return new GenericEventExecutorChooser(executors);
    }
}
上一篇下一篇

猜你喜欢

热点阅读