成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

你都理解創(chuàng)建線程池的參數(shù)嗎?

canopus4u / 3020人閱讀

摘要:超過之后的臨時(shí)線程的存活時(shí)間。為什么不建議使用創(chuàng)建線程池為我們提供了線程池工具類,里面有默認(rèn)的線程池創(chuàng)建策略,大概有以下幾種線程池線程數(shù)量固定,即和數(shù)量一樣。創(chuàng)建一個(gè)定長的線程池,而且支持定時(shí)的以及周期性的任務(wù)執(zhí)行,類似于。

微信公眾號(hào)「后端進(jìn)階」,專注后端技術(shù)分享:Java、Golang、WEB框架、分布式中間件、服務(wù)治理等等。  
老司機(jī)傾囊相授,帶你一路進(jìn)階,來不及解釋了快上車!

多線程可以說是面試官最喜歡拿來問的題目之一了,可謂是老生之常談,不管你是新手還是老司機(jī),我相信你一定會(huì)在面試過程中遇到過有關(guān)多線程的一些問題。那我現(xiàn)在就充當(dāng)一次面試官,我來問你:

現(xiàn)有一個(gè)線程池,參數(shù)corePoolSize = 5,maximumPoolSize = 10,BlockingQueue阻塞隊(duì)列長度為5,此時(shí)有4個(gè)任務(wù)同時(shí)進(jìn)來,問:線程池會(huì)創(chuàng)建幾條線程?

如果4個(gè)任務(wù)還沒處理完,這時(shí)又同時(shí)進(jìn)來2個(gè)任務(wù),問:線程池又會(huì)創(chuàng)建幾條線程還是不會(huì)創(chuàng)建?

如果前面6個(gè)任務(wù)還是沒有處理完,這時(shí)又同時(shí)進(jìn)來5個(gè)任務(wù),問:線程池又會(huì)創(chuàng)建幾條線程還是不會(huì)創(chuàng)建?

如果你此時(shí)一臉懵逼,請(qǐng)不要慌,問題不大。

創(chuàng)建線程池的構(gòu)造方法的參數(shù)都有哪些?

要回答這個(gè)問題,我們需要從創(chuàng)建線程池的參數(shù)去找答案:

java.util.concurrent.ThreadPoolExecutor#ThreadPoolExecutor:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.acc = System.getSecurityManager() == null ? null : AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

創(chuàng)建線程池一共有7個(gè)參數(shù),從源碼可知,corePoolSize和maximumPoolSize都不能小于0,且核心線程數(shù)不能大于最大線程數(shù)。

下面我來解釋一下這7個(gè)參數(shù)的用途:

corePoolSize

線程池核心線程數(shù)量,核心線程不會(huì)被回收,即使沒有任務(wù)執(zhí)行,也會(huì)保持空閑狀態(tài)。如果線程池中的線程少于此數(shù)目,則在執(zhí)行任務(wù)時(shí)創(chuàng)建。

maximumPoolSize

池允許最大的線程數(shù),當(dāng)線程數(shù)量達(dá)到corePoolSize,且workQueue隊(duì)列塞滿任務(wù)了之后,繼續(xù)創(chuàng)建線程。

keepAliveTime

超過corePoolSize之后的“臨時(shí)線程”的存活時(shí)間。

unit

keepAliveTime的單位。

workQueue

當(dāng)前線程數(shù)超過corePoolSize時(shí),新的任務(wù)會(huì)處在等待狀態(tài),并存在workQueue中,BlockingQueue是一個(gè)先進(jìn)先出的阻塞式隊(duì)列實(shí)現(xiàn),底層實(shí)現(xiàn)會(huì)涉及Java并發(fā)的AQS機(jī)制,有關(guān)于AQS的相關(guān)知識(shí),我會(huì)多帶帶寫一篇,敬請(qǐng)期待。

threadFactory

創(chuàng)建線程的工廠類,通常我們會(huì)自頂一個(gè)threadFactory設(shè)置線程的名稱,這樣我們就可以知道線程是由哪個(gè)工廠類創(chuàng)建的,可以快速定位。

handler

線程池執(zhí)行拒絕策略,當(dāng)線數(shù)量達(dá)到maximumPoolSize大小,并且workQueue也已經(jīng)塞滿了任務(wù)的情況下,線程池會(huì)調(diào)用handler拒絕策略來處理請(qǐng)求。

系統(tǒng)默認(rèn)的拒絕策略有以下幾種:

AbortPolicy:為線程池默認(rèn)的拒絕策略,該策略直接拋異常處理。

DiscardPolicy:直接拋棄不處理。

DiscardOldestPolicy:丟棄隊(duì)列中最老的任務(wù)。

CallerRunsPolicy:將任務(wù)分配給當(dāng)前執(zhí)行execute方法線程來處理。

我們還可以自定義拒絕策略,只需要實(shí)現(xiàn)RejectedExecutionHandler接口即可,友好的拒絕策略實(shí)現(xiàn)有如下:

將數(shù)據(jù)保存到數(shù)據(jù),待系統(tǒng)空閑時(shí)再進(jìn)行處理

將數(shù)據(jù)用日志進(jìn)行記錄,后由人工處理

現(xiàn)在我們回到剛開始的問題就很好回答了:

線程池corePoolSize=5,線程初始化時(shí)不會(huì)自動(dòng)創(chuàng)建線程,所以當(dāng)有4個(gè)任務(wù)同時(shí)進(jìn)來時(shí),執(zhí)行execute方法會(huì)新建【4】條線程來執(zhí)行任務(wù);

前面的4個(gè)任務(wù)都沒完成,現(xiàn)在又進(jìn)來2個(gè)隊(duì)列,會(huì)新建【1】條線程來執(zhí)行任務(wù),這時(shí)poolSize=corePoolSize,還剩下1個(gè)任務(wù),線程池會(huì)將剩下這個(gè)任務(wù)塞進(jìn)阻塞隊(duì)列中,等待空閑線程執(zhí)行;

如果前面6個(gè)任務(wù)還是沒有處理完,這時(shí)又同時(shí)進(jìn)來了5個(gè)任務(wù),此時(shí)還沒有空閑線程來執(zhí)行新來的任務(wù),所以線程池繼續(xù)將這5個(gè)任務(wù)塞進(jìn)阻塞隊(duì)列,但發(fā)現(xiàn)阻塞隊(duì)列已經(jīng)滿了,核心線程也用完了,還剩下1個(gè)任務(wù)不知道如何是好,于是線程池只能創(chuàng)建【1】條“臨時(shí)”線程來執(zhí)行這個(gè)任務(wù)了;

這里創(chuàng)建的線程用“臨時(shí)”來描述還是因?yàn)樗鼈儾粫?huì)長期存在于線程池,它們的存活時(shí)間為keepAliveTime,此后線程池會(huì)維持最少corePoolSize數(shù)量的線程。

為什么不建議使用Executors創(chuàng)建線程池?

JDK為我們提供了Executors線程池工具類,里面有默認(rèn)的線程池創(chuàng)建策略,大概有以下幾種:

FixedThreadPool:線程池線程數(shù)量固定,即corePoolSize和maximumPoolSize數(shù)量一樣。

SingleThreadPool:單個(gè)線程的線程池。

CachedThreadPool:初始核心線程數(shù)量為0,最大線程數(shù)量為Integer.MAX_VALUE,線程空閑時(shí)存活時(shí)間為60秒,并且它的阻塞隊(duì)列為SynchronousQueue,它的初始長度為0,這會(huì)導(dǎo)致任務(wù)每次進(jìn)來都會(huì)創(chuàng)建線程來執(zhí)行,在線程空閑時(shí),存活時(shí)間到了又會(huì)釋放線程資源。

ScheduledThreadPool:創(chuàng)建一個(gè)定長的線程池,而且支持定時(shí)的以及周期性的任務(wù)執(zhí)行,類似于Timer。

用Executors工具類雖然很方便,我依然不推薦大家使用以上默認(rèn)的線程池創(chuàng)建策略,阿里巴巴開發(fā)手冊(cè)也是強(qiáng)制不允許使用Executors來創(chuàng)建線程池,我們從JDK源碼中尋找一波答案:

java.util.concurrent.Executors:

// FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue());
}

// SingleThreadPool
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue()));
}

// CachedThreadPool
public static ExecutorService newCachedThreadPool() {
    // 允許創(chuàng)建線程數(shù)為Integer.MAX_VALUE
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue());
}

// ScheduledThreadPool
public ScheduledThreadPoolExecutor(int corePoolSize) {
    // 允許創(chuàng)建線程數(shù)為Integer.MAX_VALUE
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }
public LinkedBlockingQueue() {
    // 允許隊(duì)列長度最大為Integer.MAX_VALUE
    this(Integer.MAX_VALUE);
}

從JDK源碼可看出,Executors工具類無非是把一些特定參數(shù)進(jìn)行了封裝,并提供一些方法供我們調(diào)用而已,我們并不能靈活地填寫參數(shù),策略過于簡單,不夠友好。

CachedThreadPool和ScheduledThreadPool最大線程數(shù)為Integer.MAX_VALUE,如果線程無限地創(chuàng)建,會(huì)造成OOM異常。

LinkedBlockingQueue基于鏈表的FIFO隊(duì)列,是無界的,默認(rèn)大小是Integer.MAX_VALUE,因此FixedThreadPool和SingleThreadPool的阻塞隊(duì)列長度為Integer.MAX_VALUE,如果此時(shí)隊(duì)列被無限地堆積任務(wù),會(huì)造成OOM異常。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74804.html

相關(guān)文章

  • 關(guān)于線程池你不得不知道的一些設(shè)置

    摘要:有細(xì)心的網(wǎng)友早就想到了這個(gè)問題在線程池中,還有一些不常用的設(shè)置。所以該方法會(huì)在線程池總預(yù)先創(chuàng)建沒有任務(wù)執(zhí)行的線程,數(shù)量為。下面我們測試一下從測試結(jié)果來看,線程池中已經(jīng)預(yù)先創(chuàng)建了數(shù)量的空閑線程。 微信公眾號(hào)「后端進(jìn)階」,專注后端技術(shù)分享:Java、Golang、WEB框架、分布式中間件、服務(wù)治理等等。 老司機(jī)傾囊相授,帶你一路進(jìn)階,來不及解釋了快上車! 看完我上一篇文章「你都理解創(chuàng)建線...

    余學(xué)文 評(píng)論0 收藏0
  • 技術(shù)經(jīng)理:求求你,別再亂改數(shù)據(jù)庫連接池的大小了!

    摘要:你僅僅需要一個(gè)大小為數(shù)據(jù)庫連接池,然后讓剩下的業(yè)務(wù)線程都在隊(duì)列里等待就可以了。你應(yīng)該經(jīng)常會(huì)看到一些用戶量不是很大的應(yīng)用中,為應(yīng)付大約十來個(gè)的并發(fā),卻將數(shù)據(jù)庫連接池設(shè)置成,的情況。請(qǐng)不要過度配置您的數(shù)據(jù)庫連接池的大小。 文章翻譯整理自: https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing歡迎關(guān)注個(gè)人微信公眾...

    darkbug 評(píng)論0 收藏0
  • 技術(shù)經(jīng)理:求求你,別再亂改數(shù)據(jù)庫連接池的大小了!

    摘要:你僅僅需要一個(gè)大小為數(shù)據(jù)庫連接池,然后讓剩下的業(yè)務(wù)線程都在隊(duì)列里等待就可以了。你應(yīng)該經(jīng)常會(huì)看到一些用戶量不是很大的應(yīng)用中,為應(yīng)付大約十來個(gè)的并發(fā),卻將數(shù)據(jù)庫連接池設(shè)置成,的情況。請(qǐng)不要過度配置您的數(shù)據(jù)庫連接池的大小。 文章翻譯整理自: https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing歡迎關(guān)注個(gè)人微信公眾...

    蘇丹 評(píng)論0 收藏0
  • 你真的懂ThreadPoolExecutor線程池技術(shù)?看了源碼你會(huì)有全新的認(rèn)識(shí)

    摘要:參數(shù)說明,線程池保留的最小線程數(shù)。,線程池中允許擁有的最大線程數(shù)。,線程池的運(yùn)行狀態(tài)。除非線程池狀態(tài)發(fā)生了變化,發(fā)退回到外層循環(huán)重新執(zhí)行,判斷線程池的狀態(tài)。是線程池的核心控制狀態(tài),包含的線程池運(yùn)行狀態(tài)和有效線程數(shù)。 Java是一門多線程的語言,基本上生產(chǎn)環(huán)境的Java項(xiàng)目都離不開多線程。而線程則是其中最重要的系統(tǒng)資源之一,如果這個(gè)資源利用得不好,很容易導(dǎo)致程序低效率,甚至是出問題。 有...

    JerryC 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<