NOTE
Create the NioEventLoop Array
1. Code to analyze 2. Parameters passed to NioEventLoop 3. NioEventLoop is a single-threaded thread pool 4. Constructor
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:
thisis theNioEventLoopGroupitself.executoris theThreadPerTaskExecutorthat was just created, which shows that allNioEventLoopinstances share the same thread pool.SelectorProvideris 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