最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Netty組件NioEventLoopGroup創(chuàng)建線程執(zhí)行器源碼解析

 更新時(shí)間:2022年03月25日 15:38:07   作者:向南是個(gè)萬(wàn)人迷  
這篇文章主要介紹了Netty組件NioEventLoopGroup創(chuàng)建線程執(zhí)行器源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

通過(guò)上一章的學(xué)習(xí), 我們了解了Server啟動(dòng)的大致流程, 有很多組件與模塊并沒(méi)有細(xì)講, 從這個(gè)章開(kāi)始, 我們開(kāi)始詳細(xì)剖析netty的各個(gè)組件, 并結(jié)合啟動(dòng)流程, 將這些組件的使用場(chǎng)景及流程進(jìn)行一個(gè)詳細(xì)的說(shuō)明

這一章主要學(xué)習(xí)NioEventLoop相關(guān)的知識(shí),何為NioEventLoop? NioEventLoop是netty的一個(gè)線程, 在上一節(jié)我們創(chuàng)建兩個(gè)NioEventLoopGroup:

EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();

這里創(chuàng)建了兩個(gè)group, 我們提過(guò)這是boss線程組和worker線程組, 其實(shí)這兩個(gè)線程組就相當(dāng)于兩個(gè)NioEventLoop的集合, 默認(rèn)每個(gè)NioEventLoopGroup創(chuàng)建時(shí), 如果不傳入線程數(shù), 會(huì)創(chuàng)建cpu核數(shù)*2個(gè)NioEventLoop線程, 其中boss線程通過(guò)輪詢處理Server的accept事件, 而完成accept事件之后, 就會(huì)創(chuàng)建客戶端channel, 通過(guò)一定的策略, 分發(fā)到worker線程進(jìn)行處理, 而worker線程, 則主要用于處理客戶端的讀寫(xiě)事件

除了輪詢事件, EventLoop線程還維護(hù)了兩個(gè)隊(duì)列, 一個(gè)是延遲任務(wù)隊(duì)列, 另一個(gè)是普通任務(wù)隊(duì)列, 在進(jìn)行事件輪詢的同時(shí), 如果隊(duì)列中有任務(wù)需要執(zhí)行則會(huì)去執(zhí)行隊(duì)列中的任務(wù)

一個(gè)NioEventLoop綁定一個(gè)selector用于處理多個(gè)客戶端channel, 但是一個(gè)客戶端channel只能被一個(gè)NioEventLoop處理, 具體關(guān)系如圖2-0-1所示:

圖中我們看到, 一個(gè)NioEventLoopGroup下有多個(gè)NioEventLoop線程, 而一個(gè)線程可以處理多個(gè)channel, 其中有個(gè)叫pipeline和handler的東西, 同學(xué)們可能比較陌生, 這是netty的事件傳輸機(jī)制, 每個(gè)pipeline和channel唯一綁定, 這里只需要稍作了解, 之后章節(jié)會(huì)帶大家詳細(xì)剖析

了解了這些概念, 我們繼續(xù)以小節(jié)的形式對(duì)NioEventLoop進(jìn)行剖析

第一節(jié):  NioEventLoopGroup之創(chuàng)建線程執(zhí)行器

首先回到第一章最開(kāi)始的demo, 我們最初創(chuàng)建了兩個(gè)線程組:

EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();

創(chuàng)建EventLoopGroup的構(gòu)造方法

這里, 我們跟隨創(chuàng)建EventLoopGroup的構(gòu)造方法, 來(lái)繼續(xù)學(xué)習(xí)NioEventLoopGroup的創(chuàng)建過(guò)程

以workerGroup為例我們跟進(jìn)其構(gòu)造方法:

public NioEventLoopGroup() {
    this(0);
}

繼續(xù)跟進(jìn)this(0):

public NioEventLoopGroup(int nThreads) {
    this(nThreads, (Executor) null);
}

這里的nThreads就是剛傳入的0, 繼續(xù)跟進(jìn):

public NioEventLoopGroup(int nThreads, Executor executor) {
    this(nThreads, executor, SelectorProvider.provider());
}

這里nThreads仍然為0, executor為null, 這個(gè)execute是用于開(kāi)啟NioEventLoop線程所需要的線程執(zhí)行器, SelectorProvider.provider()是用于創(chuàng)建selector, 這個(gè)之后會(huì)講到

我們一直跟到構(gòu)造方法最后:

public NioEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, 
                         final SelectorProvider selectorProvider, 
                         final SelectStrategyFactory selectStrategyFactory, 
                         final RejectedExecutionHandler rejectedExecutionHandler) {
    super(nThreads, executor, chooserFactory, selectorProvider, selectStrategyFactory, rejectedExecutionHandler);
}

這里調(diào)用了父類的構(gòu)造方法

跟進(jìn)super, 進(jìn)入了其父類MultithreadEventExecutorGroup的構(gòu)造方法中:

protected MultithreadEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, 
                                 Object... args) {
    super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, chooserFactory, args);
}

這里我們看到, 如果傳入的線程數(shù)量參數(shù)為0, 則會(huì)給一個(gè)默認(rèn)值, 這個(gè)默認(rèn)值就是兩倍的CPU核數(shù), chooserFactory是用于創(chuàng)建線程選擇器, 之后會(huì)講到, 繼續(xù)跟代碼之后, 我們就看到了創(chuàng)建NioEventLoop的真正邏輯, 在MultithreadEventExecutorGroup類的構(gòu)造方法中

跟到MultithreadEventExecutorGroup類的構(gòu)造方法

protected MultithreadEventExecutorGroup(int nThreads, Executor executor, 
                                        EventExecutorChooserFactory chooserFactory, Object... args) {
    //代碼省略
    if (executor == null) {
        //創(chuàng)建一個(gè)新的線程執(zhí)行器(1)
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }
    //構(gòu)造NioEventLoop(2)
    children = new EventExecutor[nThreads];
    for (int i = 0; i < nThreads; i ++) {
        boolean success = false;
        try {
            children[i] = newChild(executor, args);
            success = true;
        } catch (Exception e) {
            throw new IllegalStateException("failed to create a child event loop", e);
        } finally {
           //代碼省略
        }
    }
    //創(chuàng)建線程選擇器(3)
    chooser = chooserFactory.newChooser(children);
    //代碼省略
}

這邊將代碼主要分為三個(gè)步驟:

1.創(chuàng)建線程執(zhí)行器

2.創(chuàng)建EventLoop

3.創(chuàng)建線程選擇器

這一小節(jié)我們主要剖析第1步, 創(chuàng)建線程執(zhí)行器

這里有個(gè)new DefaultThreadFactory()創(chuàng)建一個(gè)DefaultThreadFactory對(duì)象, 這個(gè)對(duì)象作為參數(shù)傳入ThreadPerTaskExecutor的構(gòu)造函數(shù),  DefaultThreadFactory顧名思義, 是一個(gè)線程工廠, 用于創(chuàng)建線程的, 簡(jiǎn)單看下這個(gè)類的繼承關(guān)系:

public class DefaultThreadFactory implements ThreadFactory{//類體
}

我們繼續(xù)跟進(jìn)該類的構(gòu)造方法:

protected ThreadFactory newDefaultThreadFactory() {
    return new DefaultThreadFactory(getClass());
}

其中g(shù)etClass()就是當(dāng)前類的class對(duì)象, 而當(dāng)前類是NioEventLoopGroup

繼續(xù)跟進(jìn)到DefaultThreadFactory的構(gòu)造方法中:

public DefaultThreadFactory(Class<?> poolType) {
    this(poolType, false, Thread.NORM_PRIORITY);
}

poolType是NioEventLoop的class對(duì)象, Thread.NORM_PRIORITY是設(shè)置默認(rèn)的優(yōu)先級(jí)為5

繼續(xù)跟構(gòu)造方法:

public DefaultThreadFactory(Class<?> poolType, boolean daemon, int priority) {
    this(toPoolName(poolType), daemon, priority);
}

這里的toPoolName(poolType)是將線程組命名, 這里返回后結(jié)果是"nioEventLoopGroup"(開(kāi)n頭小寫(xiě)), daemon為false, priority為5

繼續(xù)跟構(gòu)造方法:

public DefaultThreadFactory(String poolName, boolean daemon, int priority) {
    this(poolName, daemon, priority, System.getSecurityManager() == null ?
            Thread.currentThread().getThreadGroup() : System.getSecurityManager().getThreadGroup());
}

 System.getSecurityManager() == null ? Thread.currentThread().getThreadGroup() : System.getSecurityManager().getThreadGroup() 

這段代碼是通過(guò)三目運(yùn)算創(chuàng)建jdk底層的線程組

繼續(xù)跟this():

public DefaultThreadFactory(String poolName, boolean daemon, int priority, ThreadGroup threadGroup) {
    //省略驗(yàn)證代碼
    //線程名字前綴
    prefix = poolName + '-' + poolId.incrementAndGet() + '-';
    this.daemon = daemon;
    //優(yōu)先級(jí)
    this.priority = priority;
    //初始化線程組
    this.threadGroup = threadGroup;
}

這里初始化了DefaultThreadFactory的屬性, prefix為poolName(也就是nioEventLoopGroup)+'-'+線程組id(原子自增)+'-'

以及初始化了優(yōu)先級(jí)和jdk底層的線程組等屬性

回到最初MultithreadEventExecutorGroup類的構(gòu)造方法中, 我們看繼續(xù)看第一步:

//創(chuàng)建一個(gè)新的線程執(zhí)行器(1)
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());

我們繼續(xù)跟進(jìn)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) {
        //起一個(gè)線程
        threadFactory.newThread(command).start();
    }
}

我們發(fā)現(xiàn)這個(gè)類非常簡(jiǎn)單, 繼承了jdk的Executor類, 從繼承關(guān)系中我就能猜想到, 而這個(gè)類就是用于開(kāi)啟線程的線程執(zhí)行器

構(gòu)造方法傳入ThreadFactory類型的參數(shù), 這個(gè)ThreadFactory就是我們剛才剖析的DefaultThreadFactory, 這個(gè)類繼承了ThreadFactory, 所以在構(gòu)造方法中初始化了ThreadFactory類型的屬性

我們?cè)倏粗貙?xiě)的 execute(Runnable command) 方法, 傳入一個(gè)任務(wù), 然后由threadFactory對(duì)象創(chuàng)建一個(gè)線程執(zhí)行該任務(wù)

這個(gè)execute(Runnable command)方法, 其實(shí)就是用開(kāi)開(kāi)啟NioEventLoop線程用的, 那么NioEventLoop什么時(shí)候開(kāi)啟的, 后面章節(jié)會(huì)進(jìn)行剖析

這樣, 通過(guò) executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()) 這種方式就返回了一個(gè)線程執(zhí)行器Executor, 用于開(kāi)啟NioEventLoop線程

以上就是Netty組件NioEventLoopGroup創(chuàng)建線程執(zhí)行器源碼解析的詳細(xì)內(nèi)容,更多關(guān)于Netty NioEventLoopGroup線程執(zhí)行器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 手把手教你從零設(shè)計(jì)一個(gè)java日志框架

    手把手教你從零設(shè)計(jì)一個(gè)java日志框架

    Java里的各種日志框架,相信大家都不陌生。Log4j/Log4j2/Logback/jboss logging等等,其實(shí)這些日志框架核心結(jié)構(gòu)沒(méi)什么區(qū)別,只是細(xì)節(jié)實(shí)現(xiàn)上和其性能上有所不同。本文帶你從零開(kāi)始,一步一步的設(shè)計(jì)一個(gè)日志框架
    2021-02-02
  • Spring中IoC優(yōu)點(diǎn)與缺點(diǎn)解析

    Spring中IoC優(yōu)點(diǎn)與缺點(diǎn)解析

    這篇文章主要為大家詳細(xì)解析了Spring中IoC優(yōu)點(diǎn)與缺點(diǎn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • MyBatisPlus查詢報(bào)錯(cuò)Unknow?column?‘id‘?in?‘field?list‘解決分析

    MyBatisPlus查詢報(bào)錯(cuò)Unknow?column?‘id‘?in?‘field?list‘解決分析

    這篇文章主要為大家介紹了MyBatisPlus查詢報(bào)錯(cuò)Unknow?column?‘id‘?in?‘field?list‘解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Java超詳細(xì)講解設(shè)計(jì)模式中的命令模式

    Java超詳細(xì)講解設(shè)計(jì)模式中的命令模式

    命令模式是將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化,對(duì)請(qǐng)求排隊(duì)或者對(duì)請(qǐng)求做日志記錄,以及可以支持撤銷的操作
    2022-04-04
  • 使用Spring的StopWatch實(shí)現(xiàn)代碼性能監(jiān)控的方法詳解

    使用Spring的StopWatch實(shí)現(xiàn)代碼性能監(jiān)控的方法詳解

    在開(kāi)發(fā)過(guò)程中,偶爾還是需要分析代碼的執(zhí)行時(shí)間,Spring 框架提供了一個(gè)方便的工具類 StopWatch,本文將介紹 StopWatch 的基本用法,并通過(guò)示例演示如何在項(xiàng)目中使用 StopWatch 進(jìn)行代碼性能監(jiān)控
    2023-12-12
  • Java之CountDownLatch原理全面解析

    Java之CountDownLatch原理全面解析

    這篇文章主要介紹了Java之CountDownLatch原理解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 詳解Spring中bean生命周期回調(diào)方法

    詳解Spring中bean生命周期回調(diào)方法

    本篇文章主要介紹了詳解Spring中bean生命周期回調(diào)方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • 圖文詳解Java線程和線程池

    圖文詳解Java線程和線程池

    下面小編就為大家?guī)?lái)一篇詳談Java的線程和線程池。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-11-11
  • JavaIO?BufferedReader和BufferedWriter使用及說(shuō)明

    JavaIO?BufferedReader和BufferedWriter使用及說(shuō)明

    這篇文章主要介紹了JavaIO?BufferedReader和BufferedWriter使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • SpringBoot在Controller層接收參數(shù)的n種姿勢(shì)(超詳細(xì))

    SpringBoot在Controller層接收參數(shù)的n種姿勢(shì)(超詳細(xì))

    這篇文章主要介紹了SpringBoot在Controller層接收參數(shù)的常用方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-01-01

最新評(píng)論

鄢陵县| 凭祥市| 会昌县| 太和县| 茌平县| 永寿县| 体育| 民权县| 北碚区| 简阳市| 松溪县| 长宁区| 郎溪县| 启东市| 土默特左旗| 新密市| 泌阳县| 遂昌县| 朝阳市| 洪泽县| 周至县| 万源市| 南康市| 武穴市| 五常市| 卓尼县| 赤城县| 北海市| 兰溪市| 玛曲县| 怀安县| 镇巴县| 柳河县| 阳江市| 侯马市| 高雄市| 明光市| 靖西县| 班戈县| 石嘴山市| 淮南市|