NOTE

Create the NioEventLoop Array

1. Code to analyze 2. Parameters passed to NioEventLoop 3. NioEventLoop is a single-threaded thread pool 4. Constructor

JavaCreated Updated 1 min readhistorical

This is a historical learning note and may contain outdated or incomplete understanding.

1. Code to Analyze

// NioEventLoop instances in the NioEventLoopGroup pool are stored in an array.
children = new EventExecutor[nThreads];

children[i] = newChild(executor, args);

2. Parameters Passed to the NioEventLoop Constructor

Continue with newChild(executor, args) and jump to:

  • NioEventLoopGroup#newChild
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
    return new NioEventLoop(this, executor, (SelectorProvider) args[0],
        ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}

Parameters passed to the constructor:

  • this is the NioEventLoopGroup itself.
  • executor is the ThreadPerTaskExecutor that was just created, which shows that all NioEventLoop instances share the same thread pool.
  • SelectorProvider is used to create the JDK NIO selector.
  • The select strategy is DefaultSelectStrategy.INSTANCE.
  • Rejection strategy.

3. NioEventLoop Is a Single-Threaded Thread Pool

The diagram shows that NioEventLoop is also a thread pool. Tasks can be wrapped as Runnable instances and submitted to it for execution.

What is interesting is that it inherits from SingleThreadEventLoop; from the name, it appears to be a single-threaded thread pool.

4. NioEventLoop Constructor

4.1. Create the Selector

NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
             SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
    // Constructor of the parent class SingleThreadEventLoop.
    super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
    if (selectorProvider == null) {
        throw new NullPointerException("selectorProvider");
    }
    if (strategy == null) {
        throw new NullPointerException("selectStrategy");
    }
    provider = selectorProvider;
    // Create Selector.
    //unwrappedSelector = provider.openSelector();
    final SelectorTuple selectorTuple = openSelector();
    selector = selectorTuple.selector;
    unwrappedSelector = selectorTuple.unwrappedSelector;
    // Save the select strategy.
    selectStrategy = strategy;
}

A selector is created here, which means every NioEventLoop has a corresponding Selector.

Continue to the constructor of the parent class SingleThreadEventLoop.

  • SingleThreadEventLoop
protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
                                boolean addTaskWakesUp, int maxPendingTasks,
                                RejectedExecutionHandler rejectedExecutionHandler) {

    // Parent class SingleThreadEventExecutor.
    super(parent, executor, addTaskWakesUp, maxPendingTasks, rejectedExecutionHandler);
    // new LinkedBlockingQueue<Runnable>(maxPendingTasks);
    tailTasks = newTaskQueue(maxPendingTasks);
}

Continue to the parent class SingleThreadEventExecutor.

4.2. Create the Queue That Stores Tasks

  • SingleThreadEventExecutor
protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                    boolean addTaskWakesUp, int maxPendingTasks,
                                    RejectedExecutionHandler rejectedHandler) {
    // AbstractScheduledEventExecutor -> AbstractEventExecutor
    super(parent);
    this.addTaskWakesUp = addTaskWakesUp;
    this.maxPendingTasks = Math.max(16, maxPendingTasks);
    this.executor = ObjectUtil.checkNotNull(executor, "executor");
    // Queue that stores tasks.
    // new LinkedBlockingQueue<Runnable>(maxPendingTasks);
    taskQueue = newTaskQueue(this.maxPendingTasks);
    rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}

taskQueue is used when an external thread executes some Netty task. If the task is not executed inside the NioEventLoop, it is put into this task queue and later taken out and executed by the thread corresponding to the NioEventLoop.

Discussion

Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub