继承关系
虽然也实现了EventLoopGroup接口,但是不是一个组,是单个的Executor
上节看到NioEventLoopGroup的newChild方法实例化EventLoop数组
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}
new NioEventLoop()
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
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;
final SelectorTuple selectorTuple = openSelector();
selector = selectorTuple.selector;
unwrappedSelector = selectorTuple.unwrappedSelector;
selectStrategy = strategy;
}
private SelectorTuple openSelector() {
// 这与NIO中的Selector.open()方法相同
final Selector unwrappedSelector = provider.openSelector();
// 我忽略了很多代码,关系netty对selector的优化,另外写写
return new SelectorTuple(unwrappedSelector,
new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet));
}
private static final class SelectorTuple {
final Selector unwrappedSelector;
final Selector selector;
SelectorTuple(Selector unwrappedSelector) {
this.unwrappedSelector = unwrappedSelector;
this.selector = unwrappedSelector;
}
SelectorTuple(Selector unwrappedSelector, Selector selector) {
this.unwrappedSelector = unwrappedSelector;
this.selector = selector;
}
}
父类SingleThreadEventLoop
protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
boolean addTaskWakesUp, int maxPendingTasks,
RejectedExecutionHandler rejectedExecutionHandler) {
super(parent, executor, addTaskWakesUp, maxPendingTasks, rejectedExecutionHandler);
tailTasks = newTaskQueue(maxPendingTasks);
}
protected Queue<Runnable> newTaskQueue(int maxPendingTasks) {
return new LinkedBlockingQueue<Runnable>(maxPendingTasks);
}
父类SingleThreadEventExecutor
protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
boolean addTaskWakesUp, int maxPendingTasks,
RejectedExecutionHandler rejectedHandler) {
// 不往上看了,就是关联当前NioEventLoop和NioEventLoopGroup
super(parent);
this.addTaskWakesUp = addTaskWakesUp;
this.maxPendingTasks = Math.max(16, maxPendingTasks);
// 每个NioEventLoop对象有一个内部的执行器Executor
// 传入的参数executor是Group中初始化的new ThreadPerTaskExecutor(newDefaultThreadFactory());
// this是当前NioEventLoop
this.executor = ThreadExecutorMap.apply(executor, this);
// 与上边的队列tailTasks 不是一个
taskQueue = newTaskQueue(this.maxPendingTasks);
// 拒绝策略非空校验
rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}
每个NioEventLoop既实现了Executor接口,内部又有一个Executor对象(很多execute()方法,因此调用的是哪个的方法这点要明确)
先看内部的Executor对象是什么,入参executor是Group中初始化的ThreadPerTaskExecutor,eventExecutor 当前NioEventLoop
public static Executor apply(final Executor executor, final EventExecutor eventExecutor) {
ObjectUtil.checkNotNull(executor, "executor");
ObjectUtil.checkNotNull(eventExecutor, "eventExecutor");
return new Executor() {
@Override
public void execute(final Runnable command) {
executor.execute(apply(command, eventExecutor));
}
};
}
public static Runnable apply(final Runnable command, final EventExecutor eventExecutor) {
ObjectUtil.checkNotNull(command, "command");
ObjectUtil.checkNotNull(eventExecutor, "eventExecutor");
return new Runnable() {
@Override
public void run() {
// 把eventExecutor对象设置到ThreadLocal变量中
setCurrentEventExecutor(eventExecutor);
try {
command.run();
} finally {
setCurrentEventExecutor(null);
}
}
};
}
即内部的Executor对象的execute方法实际是 调用Group中实例化的ThreadPerTaskExecutor的execute方法来执行传入的command任务,可以先简单理解为新建线程执行command
public final class ThreadPerTaskExecutor implements Executor {
private final ThreadFactory threadFactory;
@Override
public void execute(Runnable command) {
threadFactory.newThread(command).start();
}
}
再看NioEventLoop.execute()方法
方法在父类SingleThreadEventExecutor#execute
SingleThreadEventExecutor中有个state变量记录当前线程状态
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;
private volatile int state = ST_NOT_STARTED;
public void execute(Runnable task) {
if (task == null) {
throw new NullPointerException("task");
}
// 判断eventLoop中的线程是否已经启动
boolean inEventLoop = inEventLoop();
// 给任务队列增加任务
addTask(task);
if (!inEventLoop) {
// 如果EventLoop中的线程未启动,启动线程
startThread();
// 如果线程终止了
if (isShutdown()) {
boolean reject = false;
try {
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变量为false,是new NioEventLoop构造函数中传入的
// wakesUpForTask返回true,即每次添加任务,eventLoop中的线程就被唤醒,被从select()阻塞状态唤醒
if (!addTaskWakesUp && wakesUpForTask(task)) {
// 此方法暂时不管,知道是唤醒就成,下章细讲
wakeup(inEventLoop);
}
}
// NioEventLoop中如果线程启动,会执行this.thread = Thread.currentThread();
// 因此此方法来判断,是否NioEventLoop已经开始执行
public boolean inEventLoop() {
return inEventLoop(Thread.currentThread());
}
public boolean inEventLoop(Thread thread) {
return thread == this.thread;
}
protected void addTask(Runnable task) {
if (task == null) {
throw new NullPointerException("task");
}
if (!offerTask(task)) {
reject(task);
}
}
final boolean offerTask(Runnable task) {
if (isShutdown()) {
reject();
}
return taskQueue.offer(task);
}
@SuppressWarnings("unused")
protected boolean wakesUpForTask(Runnable task) {
return true;
}
总的来看NioEventLoop.execute(Runnable a) 就是将任务放入任务队列,如果当前eventLoop还没有启动,创建线程并绑定线程到eventLoop
还有个小点要清楚,看代码虽然看到这,但是在new NioEventLoop的时候,NioEventLoop.execute并没有执行,内部绑定的线程并没有创建,何时创建的,在下一章ServerBootStrap
来看启动线程方法SingleThreadEventExecutor#startThread, 启动线程,启动之后执行NioEventLoop的run方法,run中会处理任务队列中的任务以及监听channel的事件
private void startThread() {
if (state == ST_NOT_STARTED) {
// 线程状态为未启动,cas更新成功后正式开始启动
if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
// 一旦启动后,再次调用NioEventLoop.execute就只是往任务队列加任务了
try {
doStartThread();
} catch (Throwable cause) {
STATE_UPDATER.set(this, ST_NOT_STARTED);
PlatformDependent.throwException(cause);
}
}
}
}
private void doStartThread() {
assert thread == null;
// 这个executor是NioEventLoop的内部执行器,execute方法就是新建线程执行入参任务
executor.execute(new Runnable() {
@Override
public void run() {
// 上边判断inEventLoop方法就是判断这个thread变量,启动线程后赋值
thread = Thread.currentThread();
if (interrupted) {
thread.interrupt();
}
boolean success = false;
updateLastExecutionTime();
try {
// 执行NioEventLoop的run方法
SingleThreadEventExecutor.this.run();
success = true;
} catch (Throwable t) {
logger.warn("Unexpected exception from an event executor: ", t);
} finally {
// 忽略了很多代码
// 执行完毕核心内容,设置线程终止状态
// 移除ThreadLocal内容等等
}
}
});
}
NioEventLoop.run方法下一章看,太复杂了