阅读 36

Netty 服务端启动流程-I_newChild

简介

接上篇,MultithreadEventExecutorGroup开始了EventLoopGroup的流程,其中最重要的一个方法就是newChild方法,其最终调用的NioEventLoopGroup中的newChild方法完成EventLoop的初始化。

newChild方法

protected EventLoop newChild(Executor executor, Object... args) throws Exception {
    // 事件循环任务队列工厂,主要为EventLoop创建 任务队列
    EventLoopTaskQueueFactory queueFactory = args.length == 4 ?
        (EventLoopTaskQueueFactory) args[3] : null;
    // 新建一个 NioEventLoop,传递了之前定义的各种参数
    return new NioEventLoop(this, executor, (SelectorProvider) args[0],
            ((SelectStrategyFactory) args[1]).newSelectStrategy(),
            (RejectedExecutionHandler) args[2], queueFactory);
}
复制代码

EventLoop的初始化

图示:

主要类调用

NioEventLoop
 -->SingleThreadEventLoop
  -->SingleThreadEventExecutor
   -->AbstractScheduledEventExecutor
    -->AbstractEventExecutor

NioEventLoop

在该类中,主要通过SelectorProvider打开一个Selector;

NioEventLoop(NioEventLoopGroup parent, Executor executor,
    SelectorProvider selectorProvider,
    SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler,
    EventLoopTaskQueueFactory queueFactory) {
    // 调用父类构造方法,在本类中 创建了 两个 任务队列
    super(parent, executor, false, 
        newTaskQueue(queueFactory), 
        newTaskQueue(queueFactory),
        rejectedExecutionHandler);
    if (selectorProvider == null) {
        throw new NullPointerException("selectorProvider");
    }
    if (strategy == null) {
        throw new NullPointerException("selectStrategy");
    }
    // 接收 SelectorProvider
    provider = selectorProvider;
    // 重要方法, 打开一个 Selector;也就是说 每一个NioEventLoop都会绑定一个Selector
    final SelectorTuple selectorTuple = openSelector();
    selector = selectorTuple.selector;
    unwrappedSelector = selectorTuple.unwrappedSelector; 
    // 接收 Select 策略
    selectStrategy = strategy;
}
复制代码

SingleThreadEventLoop

protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
    boolean addTaskWakesUp, Queue<Runnable> taskQueue, 
    Queue<Runnable> tailTaskQueue,
    RejectedExecutionHandler rejectedExecutionHandler) {
    
    // 调用父类 构造方法
    super(parent, executor, addTaskWakesUp, taskQueue, rejectedExecutionHandler);
    // 接收 尾部任务队列
    tailTasks = ObjectUtil.checkNotNull(tailTaskQueue, "tailTaskQueue");
}
复制代码

SingleThreadEventExecutor

该类中一个重要方法execute,覆写了JDK Executor接口的execute方法,主要用来启动NioEventLoop

protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
    boolean addTaskWakesUp, Queue<Runnable> taskQueue,
    RejectedExecutionHandler rejectedHandler) {
    // 调用父类构造方法,传递 parent参数
    super(parent);
    // 标识, 是否 添加任务后 唤醒
    this.addTaskWakesUp = addTaskWakesUp;

    this.maxPendingTasks = DEFAULT_MAX_PENDING_EXECUTOR_TASKS;
    // 重新 包装executor
    this.executor = ThreadExecutorMap.apply(executor, this);
    this.taskQueue = ObjectUtil.checkNotNull(taskQueue, "taskQueue");
    rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}
复制代码

AbstractScheduledEventExecutor

该类 主要与 定时任务有关

protected AbstractScheduledEventExecutor(EventExecutorGroup parent) {
    // 调用 父类构造方法
    super(parent);
}
复制代码

AbstractEventExecutor

protected AbstractEventExecutor(EventExecutorGroup parent) {
    this.parent = parent;
}
复制代码

总结

  1. 此时NioEventLoop仍未启动,只是完成了初始化,绑定了一个Selector,后续用于轮询操作;NioEventLoop启动后,执行其主要方法run,开启不断轮询操作
  2. Netty中的'线程池'-EventLoopGroup,并不是真正意义上的线程池Executor,Netty中的'线程'-EventLoop,也不是真正意义上的线程。一个事件循环组管理着 n个 事件循环(NioEventLoop);每个NioEventLoop是通过上篇提到的 创建的线程池Executor创建一个线程,并将其与NioEventLoop绑定,执行NioEventLoop的run方法;