本文主要分享服務端ServerSocketChannel所綁定的NioEventLoop的線程的創建過程
在服務端啓動流程中當執行到註冊操作時,會判斷當前線程是否是ServerSocketChannel所綁定的NioEventLoop中的線程,如果不是的話,會將註冊操作封裝成一個線程任務交給NioEventLoop中的線程去執行,相關代碼如下所示:
@Override
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
if (eventLoop == null) {
throw new NullPointerException("eventLoop");
}
if (isRegistered()) {
promise.setFailure(new IllegalStateException("registered to an event loop already"));
return;
}
if (!isCompatible(eventLoop)) {
promise.setFailure(
new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
return;
}
AbstractChannel.this.eventLoop = eventLoop;
if (eventLoop.inEventLoop()) {
register0(promise);
} else {//如果當前線程不是ServerSocketChannel所綁定的NioEventLoop中的線程
try {
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
} catch (Throwable t) {
logger.warn(
"Force-closing a channel whose registration task was not accepted by an event loop: {}",
AbstractChannel.this, t);
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
}
代碼中會調用eventLoop.inEventLoop()方法判斷當前線程是否是eventLoop中的線程,如果不是的話,會調用eventLoop.execute(Runnable runnable)方法將任務提交給eventLoop執行。
相關邏輯在父類SingleThreadEventxecutor類中實現:
/**
* 在執行註冊邏輯時,當前的線程是主線程
*/
@Override
public void execute(Runnable task) {
if (task == null) {//合法性校驗
throw new NullPointerException("task");
}
//當前線程是否是ServerSocketChannel所綁定的線程EventLoop中的線程
//當前線程是main線程,所以inEventLoop應爲false
boolean inEventLoop = inEventLoop();
addTask(task);//將線程任務添加到EventLoop中的任務隊列
if (!inEventLoop) {
startThread();//啓動線程
//如果線程已經關閉則移除上面提交到任務隊列中的任務,並調用拒絕策略,拒絕任務的執行
if (isShutdown() && removeTask(task)) {
reject();
}
}
if (!addTaskWakesUp && wakesUpForTask(task)) {
wakeup(inEventLoop);
}
}
將線程任務添加到線程的任務隊列中
protected void addTask(Runnable task) {
if (task == null) {
throw new NullPointerException("task");
}
if (!offerTask(task)) {
reject(task);
}
}
創建並啓動線程
線程的狀態枚舉
key | value | 含義 |
---|---|---|
ST_NOT_STARTED | 1 | 線程尚未啓動 |
ST_STARTED | 2 | 線程已啓動 |
ST_SHUTTING_DOWN | 3 | 線程正在關閉 |
ST_SHUTDOWN | 4 | 線程已經關閉 |
ST_TERMINATED | 5 | 線程已終止 |
//如果線程尚未啓動,則調用Unsafe修改線程的對應屬性
//調用doStartThread()方法啓動線程
private void startThread() {
if (state == ST_NOT_STARTED) {
if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
try {
doStartThread();
} catch (Throwable cause) {
STATE_UPDATER.set(this, ST_NOT_STARTED);
PlatformDependent.throwException(cause);
}
}
}
}
private void doStartThread() {
assert thread == null;//斷言當前線程爲空
//調用ThreadPerTaskExecutor的execute(Runnable task)方法執行創建線程任務
executor.execute(new Runnable() {
@Override
public void run() {
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.
for (;;) {
if (confirmShutdown()) {
break;
}
}
} finally {
try {
cleanup();
} finally {
STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
threadLock.release();
if (!taskQueue.isEmpty()) {
if (logger.isWarnEnabled()) {
logger.warn("An event executor terminated with " +
"non-empty task queue (" + taskQueue.size() + ')');
}
}
terminationFuture.setSuccess(null);
}
}
}
}
});
}
ThreadPerTaskExecutor
ThreadPerTaskExecutor類如下所示
public final class ThreadPerTaskExecutor implements Executor {
private final ThreadFactory threadFactory;
public ThreadPerTaskExecutor(ThreadFactory threadFactory) {
if (threadFactory == null) {
throw new NullPointerException("threadFactory");
}
this.threadFactory = threadFactory;
}
@Override
public void execute(Runnable command) {
threadFactory.newThread(command).start();//調用線程工程的NewThread方法創建線程並啓動
}
}
DefaultThreadFactory線程工廠的newThread方法的代碼如下所示,即通過DefaultThreadFactory線程工廠創建的線程是FastThreadLocalThread類,該類爲Netty對JDK原生的Thread類的擴展,後續文章詳細分析該類,這裏可以暫時將其視爲Thread。
@Override
public Thread newThread(Runnable r) {
Thread t = newThread(FastThreadLocalRunnable.wrap(r), prefix + nextId.incrementAndGet());
try {
if (t.isDaemon() != daemon) {//設置線程是否是守護線程
t.setDaemon(daemon);
}
if (t.getPriority() != priority) {//設置線程的優先級
t.setPriority(priority);
}
} catch (Exception ignored) {
}
return t;
}
protected Thread newThread(Runnable r, String name) {
return new FastThreadLocalThread(threadGroup, r, name);
}
NioEventLoop、SingleThreadEventExecutor和ThreadPerTaskExecutor三者的關係
NioEventLoop、SingleThreadEventExecutor和ThreadPerTaskExecutor三者的關係如下所示:
SingleThreadEventExecutor類的主要作用是執行線程任務
ThreadPerTaskExecutor類的主要作用是創建Netty線程
SingleThreadEventExecutor類是NioEventLoop的父類,ThreadPerTaskExecutor是SingleThreadEventExecutor的一個成員屬性,通過構造函數初始化。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HAQfCnKv-1579501393050)(/Users/lijiaxing/Desktop/要看的書/文章圖片/NioEventLoop、SingleThreadEventExecutor和ThreadPerTaskExecutor的關係.png)]
eventLoop.execute(Runnable task) —>
SingleThreadEventExecutor.execute(Runnable task)—>
startThread()—>
doStartThread();—>
executor.execute(Runnable task)—>
ThreadPerTaskExecutor.execute(Runnable command)—》
DefaultThreadFactory.newThread(Runnable r)
總結
1、在EventLoop執行線程任務的時候創建線程,故Netty的EventLoop中的線程是Lazy create的
2、創建EventLoop線程的調用鏈爲
eventLoop.execute(Runnable task)
—>SingleThreadEventExecutor.execute(Runnable task)
—>startThread()
—>doStartThread()
—>executor.execute(Runnable task)
—>ThreadPerTaskExecutor.execute(Runnable command)
—>DefaultThreadFactory.newThread(Runnable r)