netty創建並啓動新線程流程分析

本文主要分享服務端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)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章