Summary
NioEventLoop是SingleThreadEventLoop这个抽象类的具体实现、该线程负责注册每一个Channel到特定的Selector上并且可复用该线程。
NioEventLoop在某种意义上可以说是Reactor线程。Netty通过一个线程来处理Selector内的所有事件、业务task、和定时task。
其继承结构拓扑如下图所示
由上面我们可知、因为NioEventLoo实际上就是Reactor线程、它负责的所有IO操作、和定时task、调度task的执行、所以该类的大部分方法都是围着着以上三个功能来定义的方法。
诸如
/**
* Registers an arbitrary {@link SelectableChannel}, not necessarily created by Netty, to the {@link Selector}
* of this event loop. Once the specified {@link SelectableChannel} is registered, the specified {@code task} will
* be executed by this event loop when the {@link SelectableChannel} is ready.
*/
public void register(final SelectableChannel ch, final int interestOps, final NioTask<?> task)
/**
* Replaces the current {@link Selector} of this event loop with newly created {@link Selector}s to work
* around the infamous epoll 100% CPU bug.
* FIX: JDK空轮询的导致CPU飙升100%的bug
*/
public void rebuildSelector()
First
SingleThreadEventLoop、该类是EventLoo的抽象子类、doc解释其将会在一个线程内执行提交过来的所有task。
期内包含了一个ChannelHandle执行时的线程环境、会提供一个线程环境给它、该类即ChannelHandlerInvoker
// 并把当前executor的引用传进去
private final ChannelHandlerInvoker invoker = new DefaultChannelHandlerInvoker(this);
除此之外、此类还实现了EventLoopGroup内定义的register方法的两个重载、详细见下
/**
* Register a {@link Channel} with an {@link EventLoop} from this {@link EventLoopGroup}. The returned
* {@link ChannelFuture} will get notified once the registration is completed.
* <p>
* It's only safe to submit a new task to the {@link EventLoop} from within a
* {@link ChannelHandler} once the {@link ChannelPromise} succeeded. Otherwise
* the task may or may not be rejected.
* </p>
*/
@Override
public ChannelFuture register(Channel channel) {
return register(channel, new DefaultChannelPromise(channel, this));
}
/**
* Register a {@link Channel} with an {@link EventLoop} from this {@link EventLoopGroup}. The provided
* {@link ChannelPromise} will get notified once the registration is completed. The returned {@link ChannelFuture}
* is the same {@link ChannelPromise} that was passed to the method.
* <p>
* It's only safe to submit a new task to the {@link EventLoop} from within a
* {@link ChannelHandler} once the {@link ChannelPromise} succeeded. Otherwise
* the task may or may not be rejected.
* </p>
*/
@Override
public ChannelFuture register(final Channel channel, final ChannelPromise promise) {
if (channel == null) {
throw new NullPointerException("channel");
}
if (promise == null) {
throw new NullPointerException("promise");
}
channel.unsafe().register(this, promise);
return promise;
}
second
SingleThreadEventExecutor、该类是上文的父级抽象类、这个类是个重要的角色、隆重介绍下!
1、这个类、具体定义了线程执行生命周期的具体命名和定义、以及实现方式;
2、此类中抽象方法run、就是大名鼎鼎的Reactor线程启动的入口!该run方法是在孙辈的NioEventLoop中实现;
3、该类实现了java.util.concurrent.Executor的抽象方法execute(Runnable task)。
execute(Runnable task)方法的调用之处挺多的、这里只具一个例子、
io.netty.channel.AbstractChannel.AbstractUnsafe#register内的register0方法是封装到Runnable对象内;紧接着会异步触发SingleThreadEventExecutor内的execute方法的调用;这里仅仅举例、Channle的注册后续会详细解析。
3.1 详解SingleThreadEventExecutor#execute(Runnable task)
@Override
public void execute(Runnable task) {
if (task == null) {
throw new NullPointerException("task");
}
// 判断当前线程是否是Reactor线程
boolean inEventLoop = inEventLoop();
if (inEventLoop) {
// 若是,则将该传进来的task添加进到队列内
addTask(task);
} else {
// 若不是,则说明Reactor线程没有开启、则首先开启Reactor线程;之后再进行task的添加
startExecution();
addTask(task);
if (isShutdown() && removeTask(task)) {
reject();
}
}
if (!addTaskWakesUp && wakesUpForTask(task)) {
wakeup(inEventLoop);
}
}
分解步骤一起看下startExecution方法
private void startExecution() {
if (STATE_UPDATER.get(this) == ST_NOT_STARTED) {
// 将线程的生命周期置为已启动
if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
// 添加一个定时调度任务、为了清理队列中多余的已经被canceled的任务
schedule(new ScheduledFutureTask<Void>(
this, Executors.<Void>callable(new PurgeTask(), null),
ScheduledFutureTask.deadlineNanos(SCHEDULE_PURGE_INTERVAL), -SCHEDULE_PURGE_INTERVAL));
// 开始调度
scheduleExecution();
}
}
}
// step1、将当前线程更新为null
// step2、开始执行一个“特殊的Runnable任务”
protected final void scheduleExecution() {
updateThread(null);
executor.execute(asRunnable);
}
private final Runnable asRunnable = new Runnable() {
@Override
public void run() {
updateThread(Thread.currentThread());
// lastExecutionTime must be set on the first run
// in order for shutdown to work correctly for the
// rare case that the eventloop did not execute
// a single task during its lifetime.
// 这个最后执行时间一定在第一次线程运行的时候要被设置、是为了能够当没有task执行的时候,netty可以按照顺序逐个组关闭它们
if (firstRun) {
firstRun = false;
updateLastExecutionTime();
}
try {
// 这个地方实际上就调用了NioEventLoop中的重写的run()
SingleThreadEventExecutor.this.run();
} catch (Throwable t) {
logger.warn("Unexpected exception from an event executor: ", t);
cleanupAndTerminate(false);
}
}
};
4、此类中含有一个taskQueue的引用、该私有成员变量没有doc;所以我们大胆猜测下
private final Queue<Runnable> taskQueue;
4、1 这个taskQueue的初始化放置到SingleThreadEventExecutor类的构造方法中
/**
* Create a new {@link Queue} which will holds the tasks to execute. This default implementation will return a
* {@link LinkedBlockingQueue} but if your sub-class of {@link SingleThreadEventExecutor} will not do any blocking
* calls on the this {@link Queue} it may make sense to {@code @Override} this and return some more performant
* implementation that does not support blocking operations at all.
*/
protected Queue<Runnable> newTaskQueue() {
return new LinkedBlockingQueue<Runnable>();
}
pollTask()
/**
* @see {@link Queue#poll()}
*/
protected Runnable pollTask() {
assert inEventLoop();
for (;;) {
Runnable task = taskQueue.poll();
if (task == WAKEUP_TASK) {
continue;
}
return task;
}
}
takeTask()
/**
* Take the next {@link Runnable} from the task queue and so will block if no task is currently present.
* <p>
* Be aware that this method will throw an {@link UnsupportedOperationException} if the task queue, which was
* created via {@link #newTaskQueue()}, does not implement {@link BlockingQueue}.
* </p>
*
* @return {@code null} if the executor thread has been interrupted or waken up.
* 1、如果当前队列内是空的、则会一直阻塞
* 2、如果我们重写了newTaskQueus()、导致返回的并不是BlockingQueue则该方法则会抛异常
* 3、如果当前线程被打断、或被唤醒、则返回null
*/
protected Runnable takeTask() {
assert inEventLoop();
// 判断类型是否是阻塞队列、若不是、则直接抛出异常
if (!(taskQueue instanceof BlockingQueue)) {
throw new UnsupportedOperationException();
}
// 获取当前taskQueue的引用
BlockingQueue<Runnable> taskQueue = (BlockingQueue<Runnable>) this.taskQueue;
for (;;) {
// 从定时任务队列scheduledTaskQueue(该队列内的每个task都根据deadline自动排序,返回的是截止时间最靠前的task)内获取task;
ScheduledFutureTask<?> scheduledTask = peekScheduledTask();
if (scheduledTask == null) {
Runnable task = null;
try {
//从taskQueue获取任务
task = taskQueue.take();
if (task == WAKEUP_TASK) {
task = null;
}
} catch (InterruptedException e) {
// Ignore
}
return task;
} else {
// 获取该task的延迟时间
long delayNanos = scheduledTask.delayNanos();
Runnable task = null;
if (delayNanos > 0) {
try {
// 从taskQueue内等待delayNanos纳秒时间;
task = taskQueue.poll(delayNanos, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
// Waken up.
return null;
}
}
if (task == null) {
// We need to fetch the scheduled tasks now as otherwise there may be a chance that
// scheduled tasks are never executed if there is always one task in the taskQueue.
// This is for example true for the read task of OIO Transport
// See https://github.com/netty/netty/issues/1614
fetchFromScheduledTaskQueue();
task = taskQueue.poll();
}
if (task != null) {
return task;
}
}
}
runAllTasks() && runAllTasks(long timeoutNanos)
/**
* Poll all tasks from the task queue and run them via {@link Runnable#run()} method.
*
* @return {@code true} if and only if at least one task was run
*/
protected boolean runAllTasks() {
// 将scheduledTaskQueue内的task添加进taskQueue
fetchFromScheduledTaskQueue();
// 从taskQueue内获取task
Runnable task = pollTask();
if (task == null) {
return false;
}
for (;;) {
try {
task.run();
} catch (Throwable t) {
logger.warn("A task raised an exception.", t);
}
// 继续获取task、一直到task为null
task = pollTask();
if (task == null) {
// 此时记录下、最后一个task执行的纳秒时间
lastExecutionTime = ScheduledFutureTask.nanoTime();
return true;
}
}
}
Thrid
AbstractScheduledEventExecutor该类是上文中的抽象父类;内定义了一个scheduledTaskQueue,默认是scheduledTaskQueue;
内部定义了实时调度api的具体实现;
该类的调度Runnable对象具体实现的类为ScheduledFutureTask、后续会重点讲解该类。
Fourth
AbstractEventExecutor 实现EventExecutor接口;并继承子jdk的AbstractExecutorService抽象类