多線程之線程池

創(chuàng)建線程會(huì)產(chǎn)生系統(tǒng)開(kāi)銷(xiāo),并且每個(gè)線程會(huì)占用一定的內(nèi)存等資源,同時(shí)線程的銷(xiāo)毀也需要帶來(lái)一定的壓力。過(guò)多的線程還會(huì)帶來(lái)由于上下文切換等等的性能損耗。

使用線程池的好處:
1)提高響應(yīng)速度:通過(guò)復(fù)用線程可以消除線程創(chuàng)建銷(xiāo)毀帶來(lái)的延遲,提示響應(yīng)速度
2)降低資源消耗線程池可以統(tǒng)籌內(nèi)存和CPU的使用,避免資源使用不當(dāng),線程池會(huì)根據(jù)配置和任務(wù)數(shù)量靈活控制線程數(shù)量,不夠就創(chuàng)建,多了就回收,避免線程過(guò)多導(dǎo)致內(nèi)存溢出,過(guò)少導(dǎo)致資源浪費(fèi)
3)提高線程可管理行線程池可以統(tǒng)一管理資源,統(tǒng)一進(jìn)行分配、調(diào)優(yōu)、監(jiān)控。

一、線程池參數(shù)

1.1 線程池核心參數(shù)

1)corePoolSize
核心線程數(shù)。默認(rèn)情況核心線程會(huì)一直存活。

2)maxPoolSize
最大線程數(shù)。決定線程池最多可以創(chuàng)建多少個(gè)線程

3)KeepAliveTime+時(shí)間單位
設(shè)置線程空閑時(shí)間,當(dāng)線程空閑時(shí)間超過(guò)KeepAliveTime就會(huì)被銷(xiāo)毀。allowCoreThreadTimeOut 參數(shù)可以決定核心線程若空閑時(shí)間過(guò)長(zhǎng),是否可以被回收

4)ThreadFactory
線程工廠。用來(lái)創(chuàng)建新線程,可以對(duì)線程的屬性進(jìn)行定制,比如線程group、線程名稱(chēng)、優(yōu)先級(jí)等。

5)workQueue
存放任務(wù)的隊(duì)列,即緩沖隊(duì)列。

6)Handler
任務(wù)被拒絕時(shí)的策略
拒絕時(shí)機(jī):

  • 調(diào)用shutdown等方法關(guān)閉線程池后,此時(shí)如果再向線程池提交任務(wù),則遭到拒絕
  • 線程池沒(méi)有能力處理任務(wù)時(shí),即線程數(shù)達(dá)到了maxPoolSize,切workQueue已滿

1.2 線程池拒絕策略

拒絕策略統(tǒng)一實(shí)現(xiàn)java.util.concurrent.RejectedExecutionHandler
java在ThreadPoolExecutor中提供了其4中實(shí)現(xiàn):

  • AbortPolicy 當(dāng)需要拒接任務(wù)時(shí),直接拋出RejectedExecutionException運(yùn)行時(shí)異常
  • DiscardPolicy 當(dāng)需要拒絕任務(wù)時(shí)直接丟棄,也不會(huì)給任何通知,可能會(huì)造成數(shù)據(jù)丟失
  • DiscardOldestPolicy 當(dāng)需要拒絕任務(wù)時(shí),丟棄任務(wù)隊(duì)列中最長(zhǎng)時(shí)間未被執(zhí)行的任務(wù),同樣存在數(shù)據(jù)丟失風(fēng)險(xiǎn)
  • CallerRunsPolicy 當(dāng)需要拒絕任務(wù)時(shí),則將此任務(wù)交給提交該任務(wù)的線程去執(zhí)行。不會(huì)造成數(shù)據(jù)丟失,而且當(dāng)線程池滿負(fù)載時(shí),新來(lái)的任務(wù)由提交任務(wù)的線程去執(zhí)行,這樣主線程因?yàn)閳?zhí)行任務(wù)而被占用,也就減緩了提交新任務(wù)的速度,而線程池也可再次期間執(zhí)掉一部分任務(wù),騰出空間,相當(dāng)于給了線程池一個(gè)緩沖期,并且相當(dāng)于有一個(gè)負(fù)向反饋。

1.3 線程池常用阻塞隊(duì)列

  • ArrayBlockingQueue
  • LinkedBlockingQueue
  • SynchronizedQueue
    內(nèi)部沒(méi)有緩沖區(qū)
  • DelayedWorkQueue

三、線程池運(yùn)行過(guò)程

QQ圖片20201118223433.png

四、 常見(jiàn)線程池

4.1 FixedThreadPool

固定線程數(shù),無(wú)界隊(duì)列,由于無(wú)界隊(duì)列,會(huì)OOM。適用于任務(wù)數(shù)量不均勻、對(duì)內(nèi)存壓力不敏感場(chǎng)景。

4.2 CachedThreadPool

由于maximumPoolSize為Integer,MAX_VALUE,所以最終創(chuàng)建的線程數(shù)量會(huì)達(dá)到操作系統(tǒng)的上限或者導(dǎo)致內(nèi)存不足。適用于要求低延遲的短期任務(wù)場(chǎng)景

4.3 ScheduledThreadPool

適用于定時(shí)任務(wù)執(zhí)行場(chǎng)景,支持固定頻率和固定延時(shí)

4.4 SingleThreadExecutor

單線程線程池,適用于需要一部執(zhí)行但需要保證任務(wù)順序的場(chǎng)景

  • SingleThreadScheduledExecutor

  • ForkJoinPool
    采用分治思想,將大任務(wù)分解成多個(gè)小任務(wù)處理,然后合并結(jié)果

//TODO ForkJoinPool 需要重點(diǎn)關(guān)注

五、線程池異常捕獲機(jī)制

總而言之,使用execute方法提交任務(wù)時(shí),異??梢酝ㄟ^(guò)線程的UncaughtExceptionHandler機(jī)制捕捉異常。
而通過(guò)submit方式則不會(huì),因?yàn)閟ubmit方法會(huì)將傳入的runnable封裝為future,而future內(nèi)部執(zhí)行時(shí),直接進(jìn)行了try catch,因而異常不會(huì)被拋出去,因?yàn)榫€程池也就感知不到異常。

https://www.cnblogs.com/ncy1/articles/11629933.html

7.4 線程數(shù)量應(yīng)該設(shè)置為多少

CPU密集型任務(wù)設(shè)置為CPU核心數(shù)的1~2倍
IO密集型任務(wù)公式:CPU核心數(shù)*(1+平均等待時(shí)間(I/O)/平均工作時(shí)間(cpu計(jì)算))

7.5 線程池線程復(fù)用原理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 線程池的優(yōu)勢(shì): Thread pools address two different problems: they...
    Showdy閱讀 302評(píng)論 0 0
  • 1. ThreadPool線程池 1.1 線程池的使用 線程復(fù)用、控制最大并發(fā)數(shù)、管理線程降低資源消耗。通過(guò)重復(fù)利...
    夜小十五天閱讀 273評(píng)論 0 0
  • 一 為何使用線程池 在我們?nèi)粘5腁ndroid開(kāi)發(fā)中,經(jīng)常使用多線程來(lái)處理異步的任務(wù),第一想到的就是new Thr...
    JingChen_閱讀 689評(píng)論 0 1
  • 一、線程池的構(gòu)造 一、線程池的構(gòu)造使用線程池離不開(kāi)ThreadPoolExecutor類(lèi),該類(lèi)實(shí)現(xiàn)了Executo...
    夜風(fēng)月圓閱讀 243評(píng)論 0 0
  • 今天學(xué)習(xí)了線程池。java有各種池,對(duì)于初學(xué)者而言聽(tīng)著都頭疼。下面我們來(lái)了解一下什么是線程池。一:線程池的概述試想...
    初夏時(shí)的貓閱讀 404評(píng)論 0 3

友情鏈接更多精彩內(nèi)容