Github地址:github.com/lhj502819/n…,示例代码在example模块中
系列文章
- 你知道都有哪些I/O模型吗?
- Java NIO三大角色Channel、Buffer、Selector
- Doug lea《Scalable IO in Java》翻译
- Reactor模型你知道都有哪些吗?
- Netty服务端创建源码流程解析
- EventLoopGroup到底是个啥?
- 未完待续..
上一篇文章EventLoopGroup到底是个啥?我们对EventLoopGroup进行了详细的分析讲解,我们知道了NioEventLoopGroup持有EventLoop,那EventLoop是干啥的呢?今天我们就来对其进行分析解说,
由于我们在实际使用中都是NioEventLoop,因此就重点讲解NioEventLoop及其关联父类,其它的EventLoop实现大家感兴趣的可以自行查看阅读,由于EventLoop涉及的内容过多,因此我会分几篇来进行分析,本篇幅内容较长,请耐心观看哈。
整体概览
首先还是我们上篇文章中的类图,方便后边我们梳理类关系及类功能。
通过类图我们可以了解到一些内容:
- EventLoop接口继承了EventLoopGroup接口和OrderedEventExecutor接口,其拥有了注册Channel能力,并且对任务处理是顺序处理的
- NioEventLoop实现了SingleThreadEventLoop,说明是单线程处理任务的执行器
- NioEventLoop继承了AbstractScheduledEventExecutor,说明是可定时的执行器
相关类源码分析
EventExecutorGroup
扩展了一些方法,比如获取自己所在的EventExecutroGroup、判断当前线程是否在EventLoop中
public interface EventExecutor extends EventExecutorGroup {
/**
* Returns a reference to itself.
* 返回自己 和{@link EventExecutorGroup}一样
*/
@Override
EventExecutor next();
/**
* Return the {@link EventExecutorGroup} which is the parent of this {@link EventExecutor},
* 返回自己所属的EventExecutorGroup
*/
EventExecutorGroup parent();
/**
* Calls {@link #inEventLoop(Thread)} with {@link Thread#currentThread()} as argument
* 判断当前线程是否在EventLoop线程中
*/
boolean inEventLoop();
/**
* Return {@code true} if the given {@link Thread} is executed in the event loop,
* {@code false} otherwise.
* 判断给定的线程是否是EventLoop线程,看名字是不是不太像,可以看下子类{@link SingleThreadEventExecutor#inEventLoop(Thread)}}的实现
*/
boolean inEventLoop(Thread thread);
/**
* Return a new {@link Promise}.
* 后边的文章会进行讲解
*/
<V> Promise<V> newPromise();
/**
* Create a new {@link ProgressivePromise}.
* 后边的文章会进行讲解
*/
<V> ProgressivePromise<V> newProgressivePromise();
/**
* Create a new {@link Future} which is marked as succeeded already. So {@link Future#isSuccess()}
* will return {@code true}. All {@link FutureListener} added to it will be notified directly. Also
* every call of blocking methods will just return without blocking.
*
* 创建一个Success Future,所有监听了这个Future的Listener都会接到这个通知
*/
<V> Future<V> newSucceededFuture(V result);
/**
* Create a new {@link Future} which is marked as failed already. So {@link Future#isSuccess()}
* will return {@code false}. All {@link FutureListener} added to it will be notified directly. Also
* every call of blocking methods will just return without blocking.
*
* 创建一个 Failed Future,所有监听了这个Future的Listener都会接到这个通知
*/
<V> Future<V> newFailedFuture(Throwable cause);
/**
* 优雅关闭,方法被调用后isShuttingDown会返回true,quietPeriod时间内没有任务被提交才会真正的shutdown,如果quietPeriod时间内有任务提交进来,那quietPeriod就重新计算,
* 但也不是无限的等待,可以设置最大等待时间timeout,超过timeout无论是否有任务提交进来都shutdown
*
* @param quietPeriod the quiet period as described in the documentation
* @param timeout the maximum amount of time to wait until the executor is {@linkplain #shutdown()}
* regardless if a task was submitted during the quiet period
* @param unit the unit of {@code quietPeriod} and {@code timeout}
*
* @return the {@link #terminationFuture()}
*/
Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit);
}
复制代码
AbstractEventExecutor
对EventExecutor进行了部分默认实现,部分行为抽象,部分具体实现,各位看官老爷您看代码即可
public abstract class AbstractEventExecutor extends AbstractExecutorService implements EventExecutor {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractEventExecutor.class);
static final long DEFAULT_SHUTDOWN_QUIET_PERIOD = 2;
static final long DEFAULT_SHUTDOWN_TIMEOUT = 15;
/**
* 自己所属的EventExecutorGroup,初始化时指定
*/
private final EventExecutorGroup parent;
/**
* 只有自己,遍历时使用{@link #iterator()}
*/
private final Collection<EventExecutor> selfCollection = Collections.<EventExecutor>singleton(this);
protected AbstractEventExecutor() {
this(null);
}
protected AbstractEventExecutor(EventExecutorGroup parent) {
this.parent = parent;
}
@Override
public EventExecutorGroup parent() {
return parent;
}
/**
* next获取自己
*/
@Override
public EventExecutor next() {
return this;
}
/**
* 判断当前线程是否在EventLoop中,不指定线程就使用当前线程,具体的判断逻辑由子类实现,这里还只是进行抽象实现
*/
@Override
public boolean inEventLoop() {
return inEventLoop(Thread.currentThread());
}
@Override
public Iterator<EventExecutor> iterator() {
return selfCollection.iterator();
}
/**
* 设置默认的shutdown参数,实现自{@link EventExecutorGroup},安静期为2s,最大等待时间为15s
*
* 优雅关闭,方法被调用后isShuttingDown会返回true,quietPeriod时间内没有任务被提交才会真正的shutdown,如果quietPeriod时间内有任务提交进来,那quietPeriod就重新计算,
* 但也不是无限的等待,可以设置最大等待时间timeout,超过timeout无论是否有任务提交进来都shutdown
*/
@Override
public Future<?> shutdownGracefully() {
return shutdownGracefully(DEFAULT_SHUTDOWN_QUIET_PERIOD, DEFAULT_SHUTDOWN_TIMEOUT, TimeUnit.SECONDS);
}
/**
* 还是进行默认实现,至于 Promise 是啥,我们后边会有单独的文章进行讲解
*/
@Override
public <V> Promise<V> newPromise() {
return new DefaultPromise<V>(this);
}
/**
* 还是进行默认实现,至于 ProgressivePromise 是啥,我们后边会有单独的文章进行讲解
*/
@Override
public <V> ProgressivePromise<V> newProgressivePromise() {
return new DefaultProgressivePromise<V>(this);
}
/**
* 这里就不是默认实现了,就是具体实现了,把自己作为Executor、result传了进去,既然是SucceededFuture,那肯定是需要执行结果的
*/
@Override
public <V> Future<V> newSucceededFuture(V result) {
return new SucceededFuture<V>(this, result);
}
/**
* 这里就不是默认实现了,就是具体实现了,把自己作为Executor、result传了进去,既然是FailedFuture,那肯定是需要失败原因的
*/
@Override
public <V> Future<V> newFailedFuture(Throwable cause) {
return new FailedFuture<V>(this, cause);
}
/**
* 这里调用父类 {@link AbstractExecutorService#submit(Runnable)}提交任务,具体代码我贴到下边了,方便大家观看(是不是很贴心 哈哈)
*
* public Future<?> submit(Runnable task) {
* if (task == null) throw new NullPointerException();
* RunnableFuture<Void> ftask = newTaskFor(task, null);
* execute(ftask);
* return ftask;
*}
* 其中newTaskFor被当前类重写了,execute方法并没有被当前类重写,但肯定也是被Netty的某个实现类重写了,不要慌,等会儿我们就知道了
*
*/
@Override
public Future<?> submit(Runnable task) {
return (Future<?>) super.submit(task);
}
...........省略部分...............
/**
* 重写父类{@link AbstractExecutorService#newTaskFor} (Runnable)},创建PromiseTask
* 这里不禁感叹Netty作者的牛逼,把Doug lea大神的代码吃的透透的
*/
@Override
protected final <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new PromiseTask<T>(this, runnable, value);
}
/**
* 没有做定时的实现,因为有专门干这个的 {@link AbstractScheduledEventExecutor },这就是传说中的单一职责喽..
*/
@Override
public ScheduledFuture<?> schedule(Runnable command, long delay,
TimeUnit unit) {
throw new UnsupportedOperationException();
}
@Override
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
throw new UnsupportedOperationException();
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
throw new UnsupportedOperationException();
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
throw new UnsupportedOperationException();
}
/**
* Try to execute the given {@link Runnable} and just log if it throws a {@link Throwable}.
*
* 安全的执行任务,异常了就只打印个日志。。暂未领会到含义
*/
protected static void safeExecute(Runnable task) {
try {
task.run();
} catch (Throwable t) {
logger.warn("A task raised an exception. Task: {}", task, t);
}
}
}
复制代码
AbstractScheduledEventExecutor
看名字就知道这哥们是干啥的了,负责定时调度相关的,并且这是后来抽出来的一位,别问我咋知道,我去翻了老版本哈哈,是在 SingleThreadEventExecutor
中实现的,但我们今天先不讲它,后边我们会单独对这部分进行讲解,不好意思了铁铁,生气的话就点个赞发泄发泄。
SingleThreadEventExecutor
基于单线程的EventExecutor
抽象类,实现了OrderedEventExecutor
,OrderedEventExecutor
是一个标记接口,表示任务顺序执行。
这位老大哥的内容有点儿多,大家还要认真看下去呀,坚持就是胜利,看完就有收获!
内部变量
/**
* 默认的任务队列taskQueue最大值
*/
static final int DEFAULT_MAX_PENDING_EXECUTOR_TASKS = Math.max(16,
SystemPropertyUtil.getInt("io.netty.eventexecutor.maxPendingTasks", Integer.MAX_VALUE));
private static final Runnable NOOP_TASK = new Runnable() {
@Override
public void run() {
// Do nothing.
}
};
/**
* Executor当前状态
*/
@SuppressWarnings({ "FieldMayBeFinal", "unused" })
private volatile int state = ST_NOT_STARTED;
/**
* Executor的状态值
*/
private static final int ST_NOT_STARTED = 1;//未开始
private static final int ST_STARTED = 2;//运行中
private static final int ST_SHUTTING_DOWN = 3;//正在关闭中
private static final int ST_SHUTDOWN = 4;//已关闭
private static final int ST_TERMINATED = 5;//已终止
/**
* 字段的原子更新器,用的是JDK带的AtomicIntegerFieldUpdater,是不是没见过这个,我也没见过哈哈哈哈
*/
private static final AtomicIntegerFieldUpdater<SingleThreadEventExecutor> STATE_UPDATER =
AtomicIntegerFieldUpdater.newUpdater(SingleThreadEventExecutor.class, "state");
/**
* 字段原子更新器
*/
private static final AtomicReferenceFieldUpdater<SingleThreadEventExecutor, ThreadProperties> PROPERTIES_UPDATER =
AtomicReferenceFieldUpdater.newUpdater(
SingleThreadEventExecutor.class, ThreadProperties.class, "threadProperties");
/**
* 任务队列
*/
private final Queue<Runnable> taskQueue;
/**
* 持有的EventLoop线程,{@link #doStartThread()}中赋值的
*/
private volatile Thread thread;
/**
* 线程属性
*/
@SuppressWarnings("unused")
private volatile ThreadProperties threadProperties;
/**
* 执行器
*/
private final Executor executor;
/**
* 线程是否已经被打断
*/
private volatile boolean interrupted;
private final CountDownLatch threadLock = new CountDownLatch(1);
/**
* 关闭的钩子函数
*/
private final Set<Runnable> shutdownHooks = new LinkedHashSet<Runnable>();
/**
* 添加任务时是否会自动唤醒执行线程 {@link #thread}
* 可能有小伙伴会问这里为什么不是添加任务是是否自动唤醒执行线程呢?大家可以看下这个变量的由来:https://github.com/netty/netty/commit/23d017849429c18e1890b0a5799e5262df4f269f
* 其中作者进行了解释:就是之前在执行{@link #execute(Runnable, boolean)}方法时总是会在添加完任务后自动添加一个空任务到队列中唤醒执行线程,而为什么会需要唤醒呢?
* 因为NioEventLoop基于Java的Selector实现的,当我们像队列中添加任务时,Selector无法感知,因此需要去触发唤醒,NioEventLoop在实例化的时候该参数就是false,表示不会自动唤醒执行线程,需要手动唤醒
* 下边是作者的解释:
* Add a constructor parameter that tells not to add an unncessary wakeup
* task in execute() if addTask() wakes up the executor thread
* automatically. Previously, execute() always called wakeup() after
* addTask(), which often caused an extra dummy task in the task queue.
*/
private final boolean addTaskWakesUp;
/**
* 最大等待执行任务数量,即{@link taskQueue}队列的大小
*/
private final int maxPendingTasks;
复制代码
构造函数
构造函数大家自行看下即可哈,就不过多解析了
/**
* Create a new instance
*
* @param parent the {@link EventExecutorGroup} which is the parent of this instance and belongs to it
* @param executor the {@link Executor} which will be used for executing
* @param addTaskWakesUp {@code true} if and only if invocation of {@link #addTask(Runnable)} will wake up the
* executor thread
* @param maxPendingTasks the maximum number of pending tasks before new tasks will be rejected.
* @param rejectedHandler the {@link RejectedExecutionHandler} to use.
*/
protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
boolean addTaskWakesUp, int maxPendingTasks,
RejectedExecutionHandler rejectedHandler) {
super(parent);
this.addTaskWakesUp = addTaskWakesUp;
this.maxPendingTasks = Math.max(16, maxPendingTasks);
this.executor = ThreadExecutorMap.apply(executor, this);
taskQueue = newTaskQueue(this.maxPendingTasks);
rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}
复制代码
以下为重要方法
添加任务
/**
* 默认使用阻塞队列用来存放即将被执行的任务,子类可进行重写 {@link NioEventLoop} 就对其进行了重写,实现了非阻塞模式,下边会进行对应的讲解
*/
protected Queue<Runnable> newTaskQueue(int maxPendingTasks) {
return new LinkedBlockingQueue<Runnable>(maxPendingTasks);
}
复制代码
execute()
添加异步任务到taskQueue,在服务端创建的源码流程分析文章中我们看到过很多这样的代码:eventLoop().execute(newRunnable()->{......})
,底层就会调用这个方法添加任务,简单来讲就是为了异步化,同时单个线程执行又不会有多线程执行的并发问题。
/**
* 添加单个任务,看名字像是执行任务是不?
* @param immediate 是否立即执行
*/
private void execute(Runnable task, boolean immediate) {
boolean inEventLoop = inEventLoop();
//将任务添加到队列中
addTask(task);
//如果当前线程不是EventLoop持有的线程
if (!inEventLoop) {
//启动线程
startThread();
if (isShutdown()) {
boolean reject = false;
try {
//如果EventLoop已经关闭了,则移除任务
if (removeTask(task)) {
reject = true;
}
} catch (UnsupportedOperationException e) {
// The task queue does not support removal so the best thing we can do is to just move on and
// hope we will be able to pick-up the task before its completely terminated.
// In worst case we will log on termination.
}
if (reject) {
reject();
}
}
}
/**
* 这里对addTaskWakesUp进行了取反,{@link #addTaskWakesUp} 表示的是添加任务时是否会自动唤醒执行线程,如果为false表示不会自动唤醒,因此这里就需要手动触发唤醒
*/
if (!addTaskWakesUp && immediate) {
wakeup(inEventLoop);
}
}
/**
* 唤醒线程,{@link NioEventLoop}对其进行了重写,后边会进行介绍
* @param inEventLoop
*/
protected void wakeup(boolean inEventLoop) {
//如果当前线程已经在EventLoop的线程中了,那就表示已经在执行了,就不用唤醒了
if (!inEventLoop) {
// Use offer as we actually only need this to unblock the thread and if offer fails we do not care as there
// is already something in the queue.
taskQueue.offer(WAKEUP_TASK);
}
}
/**
* Add a task to the task queue, or throws a {@link RejectedExecutionException} if this instance was shutdown
* before.
* 添加任务到队列中
*/
protected void addTask(Runnable task) {
ObjectUtil.checkNotNull(task, "task");
if (!offerTask(task)) {
//如果添加失败,则触发拒绝策略
reject(task);
}
}
final boolean offerTask(Runnable task) {
if (isShutdown()) {
reject();
}
return taskQueue.offer(task);
}
/**
* 启动线程执行任务
*/
private void startThread() {
if (state == ST_NOT_STARTED) {
//如果Executor状态为未启动,则使用原子类设置状态为已启动
if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
boolean success = false;
try {
doStartThread();
success = true;
} finally {
if (!success) {
//如果启动失败,则再将线程状态还原为未启动
STATE_UPDATER.compareAndSet(this, ST_STARTED, ST_NOT_STARTED);
}
}
}
}
}
/**
* 方法有点儿长,但是非常的精髓,你忍一下,哈哈
*/
private void doStartThread() {
assert thread == null;
/**
* 丢给Executor执行
* 这里使用ThreadExecutorMap包装了一层,在执行前后将执行任务的EventExecutor分别进行了绑定和解绑操作,并且自定义了TheadLocal(FastThreadLocal),性能上比JDK的TheadLocal要高
* 具体实现细节我们就不再阐述了
*/
executor.execute(new Runnable() {
@Override
public void run() {
//将当前线程设置为Executor持有的线程
thread = Thread.currentThread();
if (interrupted) {
thread.interrupt();
}
boolean success = false;
//更新最后执行任务时间
updateLastExecutionTime();
try {
//执行任务
SingleThreadEventExecutor.this.run();
//标记任务执行成功
success = true;
} catch (Throwable t) {
logger.warn("Unexpected exception from an event executor: ", t);
} finally {
for (;;) {
//优雅关闭
int oldState = state;
if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
break;
}
}
// Check if confirmShutdown() was called at the end of the loop.
if (success && gracefulShutdownStartTime == 0) {
if (logger.isErrorEnabled()) {
logger.error("Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +
SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must " +
"be called before run() implementation terminates.");
}
}
try {
// Run all remaining tasks and shutdown hooks. At this point the event loop
// is in ST_SHUTTING_DOWN state still accepting tasks which is needed for
// graceful shutdown with quietPeriod.
//这里的注释讲的很清楚了,就是当前EventLoop还是正在关闭中的状态,还能继续接受任务,因此需要在安静期内执行未完成的任务和关闭的钩子函数,还有定时任务
for (;;) {
if (confirmShutdown()) {
break;
}
}
// Now we want to make sure no more tasks can be added from this point. This is
// achieved by switching the state. Any new tasks beyond this point will be rejected.
//这里的注释讲的也很清楚了,通过EventLoop的状态控制确保没有任务再添加进来了,所有的任务都会被拒绝
for (;;) {
int oldState = state;
//修改EventLoop的状态为已关闭
if (oldState >= ST_SHUTDOWN || STATE_UPDATER.compareAndSet(
SingleThreadEventExecutor.this, oldState, ST_SHUTDOWN)) {
break;
}
}
// We have the final set of tasks in the queue now, no more can be added, run all remaining.
// No need to loop here, this is the final pass.
//最后确认所有的任务都执行完了,非常严谨
confirmShutdown();
} finally {
try {
//关闭一些资源,子类自行实现的
cleanup();
} finally {
// Lets remove all FastThreadLocals for the Thread as we are about to terminate and notify
// the future. The user may block on the future and once it unblocks the JVM may terminate
// and start unloading classes.
// See https://github.com/netty/netty/issues/6596.
//移出当前线程所有的FastThreadLocals
FastThreadLocal.removeAll();
//设置状态为已终止
STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
threadLock.countDown();
//将剩余的任务扔掉,上边已经确保任务都执行完了,不知道为啥还要执行一次,但肯定是有它的原因的
int numUserTasks = drainTasks();
if (numUserTasks > 0 && logger.isWarnEnabled()) {
logger.warn("An event executor terminated with " +
"non-empty task queue (" + numUserTasks + ')');
}
terminationFuture.setSuccess(null);
}
}
}
}
});
}
复制代码
执行所有任务队列中的任务
/**
* 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
* 轮询任务队列的任务并执行,只要有一个执行成功就返回true
*/
protected boolean runAllTasks() {
assert inEventLoop();
boolean fetchedAll;
boolean ranAtLeastOne = false;
do {
//先确保所有的定时任务被添加到任务队列中
fetchedAll = fetchFromScheduledTaskQueue();
//执行所有的任务,这里的任务就包含了定时任务
if (runAllTasksFrom(taskQueue)) {
ranAtLeastOne = true;
}
} while (!fetchedAll); // keep on processing until we fetched all scheduled tasks.
if (ranAtLeastOne) {
//如果至少执行了一个任务,则设置最终执行任务的时间为当前时间
lastExecutionTime = ScheduledFutureTask.nanoTime();
}
//执行完之后做点儿啥,留给子类扩展使用的
afterRunningAllTasks();
return ranAtLeastOne;
}
/**
* Poll all tasks from the task queue and run them via {@link Runnable#run()} method. This method stops running
* the tasks in the task queue and returns if it ran longer than {@code timeoutNanos}.
*
* 执行所有的任务,与{@link #runAllTasks()}不同的是增加了任务的执行超时时间,注意是整个任务队列所有任务的执行时间
*/
protected boolean runAllTasks(long timeoutNanos) {
//还是将所有的定时任务添加到任务队列中
fetchFromScheduledTaskQueue();
Runnable task = pollTask();
if (task == null) {
afterRunningAllTasks();
return false;
}
//计算超时的时间
final long deadline = timeoutNanos > 0 ? ScheduledFutureTask.nanoTime() + timeoutNanos : 0;
long runTasks = 0;
long lastExecutionTime;
for (;;) {
safeExecute(task);
runTasks ++;
// Check timeout every 64 tasks because nanoTime() is relatively expensive.
// XXX: Hard-coded value - will make it configurable if it is really a problem.
//每64个任务判断一次超时,nanoTime()方法太昂贵
if ((runTasks & 0x3F) == 0) {
lastExecutionTime = ScheduledFutureTask.nanoTime();
if (lastExecutionTime >= deadline) {
//如果已经超时则停止执行任务
break;
}
}
task = pollTask();
if (task == null) {
lastExecutionTime = ScheduledFutureTask.nanoTime();
break;
}
}
afterRunningAllTasks();
this.lastExecutionTime = lastExecutionTime;
return true;
}
/**
* 将所有的定时任务添加到任务队列中
* @return
*/
private boolean fetchFromScheduledTaskQueue() {
if (scheduledTaskQueue == null || scheduledTaskQueue.isEmpty()) {
return true;
}
long nanoTime = AbstractScheduledEventExecutor.nanoTime();
for (;;) {
Runnable scheduledTask = pollScheduledTask(nanoTime);
if (scheduledTask == null) {
return true;
}
if (!taskQueue.offer(scheduledTask)) {
// No space left in the task queue add it back to the scheduledTaskQueue so we pick it up again.
scheduledTaskQueue.add((ScheduledFutureTask<?>) scheduledTask);
return false;
}
}
}
protected final boolean runAllTasksFrom(Queue<Runnable> taskQueue) {
//获取并删除头任务
Runnable task = pollTaskFrom(taskQueue);
if (task == null) {
return false;
}
for (;;) {
//不断的从队列中取任务执行,直到取完
safeExecute(task);
task = pollTaskFrom(taskQueue);
if (task == null) {
return true;
}
}
}
/**
* {@link AbstractEventExecutor}
*/
protected static void safeExecute(Runnable task) {
try {
task.run();
} catch (Throwable t) {
logger.warn("A task raised an exception. Task: {}", task, t);
}
}
复制代码
关闭的钩子函数
public void addShutdownHook(final Runnable task) {
if (inEventLoop()) {
shutdownHooks.add(task);
} else {
execute(new Runnable() {
@Override
public void run() {
shutdownHooks.add(task);
}
});
}
}
复制代码
优雅关闭相关
在#execut
方法的finally代码块中也有涉猎,大家需要返回去配合观看
/**
* Confirm that the shutdown if the instance should be done now!
* 确认是否可以关闭
*/
protected boolean confirmShutdown() {
if (!isShuttingDown()) {
//如果当前的状态为运行中,则返回false,不能关闭
return false;
}
if (!inEventLoop()) {
throw new IllegalStateException("must be invoked from an event loop");
}
/**
* 取消定时任务
*/
cancelScheduledTasks();
if (gracefulShutdownStartTime == 0) {
gracefulShutdownStartTime = ScheduledFutureTask.nanoTime();
}
//运行未执行的任务
if (runAllTasks() || runShutdownHooks()) {
if (isShutdown()) {
// Executor shut down - no new tasks anymore.
return true;
}
// There were tasks in the queue. Wait a little bit more until no tasks are queued for the quiet period or
// terminate if the quiet period is 0.
// See https://github.com/netty/netty/issues/4241
if (gracefulShutdownQuietPeriod == 0) {
//如果安静期为0,则返回可以关闭
return true;
}
taskQueue.offer(WAKEUP_TASK);
//如果队列中有任务,则返回false,执行一会儿
return false;
}
final long nanoTime = ScheduledFutureTask.nanoTime();
//判断是否已经到了优雅关机的超时时间
if (isShutdown() || nanoTime - gracefulShutdownStartTime > gracefulShutdownTimeout) {
//到了就返回true,直接关机
return true;
}
//当前时间 - 最后执行时间小于安静期,表示安静期内有任务执行了,则还不能关闭
if (nanoTime - lastExecutionTime <= gracefulShutdownQuietPeriod) {
// Check if any tasks were added to the queue every 100ms.
// TODO: Change the behavior of takeTask() so that it returns on timeout.
taskQueue.offer(WAKEUP_TASK);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// Ignore
}
return false;
}
// No tasks were added for last quiet period - hopefully safe to shut down.
// (Hopefully because we really cannot make a guarantee that there will be no execute() calls by a user.)
//安静期没有任务执行了,可以关闭
return true;
}
public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
ObjectUtil.checkPositiveOrZero(quietPeriod, "quietPeriod");
if (timeout < quietPeriod) {
throw new IllegalArgumentException(
"timeout: " + timeout + " (expected >= quietPeriod (" + quietPeriod + "))");
}
ObjectUtil.checkNotNull(unit, "unit");
if (isShuttingDown()) {
return terminationFuture();
}
boolean inEventLoop = inEventLoop();
boolean wakeup;
int oldState;
for (;;) {
if (isShuttingDown()) {
//如果已经关闭了则返回终止Future
return terminationFuture();
}
int newState;
wakeup = true;
oldState = state;
if (inEventLoop) {
//设置状态为正在关闭
newState = ST_SHUTTING_DOWN;
} else {
switch (oldState) {
case ST_NOT_STARTED:
case ST_STARTED:
//如果目前的状态为正在运行,则设置状态为正在关闭
newState = ST_SHUTTING_DOWN;
break;
default:
newState = oldState;
wakeup = false;
}
}
if (STATE_UPDATER.compareAndSet(this, oldState, newState)) {
break;
}
}
/**
* 覆盖默认值,这里会和{@link #confirmShutdown()}配合
*/
gracefulShutdownQuietPeriod = unit.toNanos(quietPeriod);
gracefulShutdownTimeout = unit.toNanos(timeout);
//既然是优雅关闭,要确保线程是运行的
if (ensureThreadStarted(oldState)) {
return terminationFuture;
}
if (wakeup) {
//如果当前Executor的状态为正在运行,则需要唤醒线程
taskQueue.offer(WAKEUP_TASK);
if (!addTaskWakesUp) {
wakeup(inEventLoop);
}
}
return terminationFuture();
}
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
ObjectUtil.checkNotNull(unit, "unit");
if (inEventLoop()) {
throw new IllegalStateException("cannot await termination of the current thread");
}
threadLock.await(timeout, unit);
return isTerminated();
}
复制代码
SingleThreadEventLoop
基于单线程的EventLoop抽象类,单线程执行所有的任务,主要增加了Channel注册到EventLoop上
public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop {
/**
* 任务队列默认最大容量
*/
protected static final int DEFAULT_MAX_PENDING_TASKS = Math.max(16,
SystemPropertyUtil.getInt("io.netty.eventLoop.maxPendingTasks", Integer.MAX_VALUE));
@Override
public ChannelFuture register(Channel channel) {
//通过Channel和EventLoop创建ChannelPromise,通过ChannelPromise对象就能实现对异步注册过程的监听
return register(new DefaultChannelPromise(channel, this));
}
@Override
public ChannelFuture register(final ChannelPromise promise) {
ObjectUtil.checkNotNull(promise, "promise");
//注册Channel到EventLoop上
promise.channel().unsafe().register(this, promise);
//返回Promise
return promise;
}
}
复制代码
NioEventLoop
实现对注册到其中的 Channel 的就绪的 IO 事件处理,和对用户提交的任务进行处理,篇幅过多,我们放到下一篇文章讲解。
我是壹氿,感谢各位小伙伴点赞、收藏和评论,文章持续更新,我们下期再见!
有问题的小伙伴可以加我的个人VX交流沟通:lhj502819
同时可以关注下我的公众号:LiHongjian502819,一起努力冲击大厂。