Netty入门 - 任务加入异步线程池源码剖析
Netty 是一个高性能的异步事件驱动框架,其核心之一是任务的异步执行机制。Netty 使用 EventLoop
处理 I/O 事件,同时允许将任务提交到异步线程池中进行处理。本文将对 Netty 中任务加入异步线程池的源码进行剖析,帮助理解其工作原理和实现机制。
1. EventLoop
和 EventExecutor
EventLoop
继承自 EventExecutor
,负责管理事件循环和任务的执行。EventExecutor
提供了提交任务的方法,如 submit(Runnable task)
和 execute(Runnable command)
。
public interface EventExecutor extends ScheduledExecutorService, OrderedEventExecutor {
@Override
<V> Future<V> submit(Runnable task, V result);
@Override
Future<?> submit(Runnable task);
@Override
void execute(Runnable command);
}
2. SingleThreadEventLoop
的任务执行机制
SingleThreadEventLoop
是 EventLoop
的具体实现类,负责任务的执行。它继承自 SingleThreadEventExecutor
,后者实现了任务队列和任务执行的核心逻辑。
public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop {
protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor, boolean addTaskWakesUp,
Queue<Runnable> taskQueue, RejectedExecutionHandler rejectedHandler) {
super(parent, executor, addTaskWakesUp, taskQueue, rejectedHandler);
}
@Override
public EventLoopGroup parent() {
return (EventLoopGroup) super.parent();
}
@Override
public EventLoop next() {
return (EventLoop) super.next();
}
}
3. 任务提交和执行
在 SingleThreadEventExecutor
中,任务通过 execute(Runnable task)
方法提交到任务队列中,并由事件循环线程执行。
@Override
public void execute(Runnable task) {
if (task == null) {
throw new NullPointerException("task");
}
boolean inEventLoop = inEventLoop();
addTask(task);
if (!inEventLoop) {
startThread();
if (isShutdown() && removeTask(task)) {
reject();
}
}
if (wakesUpForTask(task)) {
wakeup(inEventLoop);
}
}
protected void addTask(Runnable task) {
if (task == null) {
throw new NullPointerException("task");
}
if (isShutdown()) {
reject();
}
taskQueue.add(task);
}
addTask(Runnable task)
方法将任务添加到任务队列中,并调用 startThread()
启动事件循环线程。
4. 事件循环线程
事件循环线程负责从任务队列中取出任务并执行。SingleThreadEventExecutor
的 run()
方法实现了事件循环的核心逻辑。
@Override
protected void run() {
for (;;) {
Runnable task = takeTask();
if (task != null) {
task.run();
updateLastExecutionTime();
}
if (confirmShutdown()) {
break;
}
}
}
takeTask()
方法从任务队列中取出任务并执行,updateLastExecutionTime()
更新任务的最后执行时间。
5. 任务队列
任务队列用于存储提交的任务,SingleThreadEventExecutor
使用一个 Queue<Runnable>
来管理任务队列。默认情况下,Netty 使用 MpscQueue
作为任务队列的实现。
protected final Queue<Runnable> taskQueue;
protected Queue<Runnable> newTaskQueue(int maxPendingTasks) {
return PlatformDependent.newMpscQueue(maxPendingTasks);
}
6. 异步任务执行
Netty 提供了一种机制,可以将任务提交到异步线程池中执行。可以通过 execute()
方法将任务提交到 EventLoop
,由 EventLoop
管理的线程池执行这些任务。
public class DefaultEventLoop extends SingleThreadEventLoop {
public DefaultEventLoop() {
this(null);
}
public DefaultEventLoop(Executor executor) {
super(null, executor, true, new LinkedBlockingQueue<Runnable>(), RejectedExecutionHandlers.reject());
}
}
DefaultEventLoop
是 SingleThreadEventLoop
的具体实现类,使用 LinkedBlockingQueue
作为任务队列,并提供默认的拒绝策略。
总结
Netty 的任务异步执行机制通过 EventLoop
和 SingleThreadEventExecutor
实现。任务提交到任务队列中,由事件循环线程执行。SingleThreadEventLoop
通过 run()
方法实现了事件循环,确保高效地处理任务和 I/O 事件。通过对源码的剖析,可以深入理解 Netty 的异步执行模型及其高性能设计。