線程池查漏補(bǔ)缺

tomcat線程池和jdk線程池區(qū)別

概述

  1. 線程池是什么,為什么要線程池
  2. jdk有哪些線程池和原理
  3. 第三方中間件的線程池特點(diǎn)
  • tomcat線程池
  • quartz線程池
  1. 線程池展望

線程池是什么,為什么要線程池

我們?cè)陧?xiàng)目啟動(dòng)后,因?yàn)镃PU是多核的,為了充分利用CPU,可能需要啟動(dòng)多個(gè)線程去處理任務(wù)。頻繁的創(chuàng)建銷毀線程是有開銷的。所以需要?jiǎng)?chuàng)建線程后緩存住,讓線程可以頻繁的處理各種任務(wù)。這個(gè)時(shí)候就需要用線程池。線程池一般會(huì)緩存住N個(gè)線程,然后往線程池里面扔任務(wù)Runnable,線程不斷的處理任務(wù)。處理完了后停留在那里等待。

jdk有哪些線程池和原理

jdk線程池主要入口是在java.util.concurrent.Executors,其中包含

  • Executors.newFixedThreadPool 固定核心數(shù)的線程池,有多余任務(wù)往無(wú)界隊(duì)列中放

  • Executors.newSingleThreadExecutor 單線程的線程池,有多余任務(wù)往無(wú)界隊(duì)列中放

  • Executors.newCachedThreadPool 有任務(wù)來(lái)就開辟新的線程,不緩存任務(wù),不緩存線程。

  • Executors.newSingleThreadScheduledExecutor 單線程的延遲線程池,也就是說(shuō)可以指定任務(wù)N秒后周期性執(zhí)行。

  • Executors.newScheduledThreadPool N線程的延遲線程池,也就是說(shuō)可以指定任務(wù)N秒后周期性執(zhí)行。
    * 這個(gè)線程池內(nèi)部依賴于ScheduledThreadPoolExecutor,隊(duì)列依賴于ScheduledThreadPoolExecutor.DelayedWorkQueue,這個(gè)隊(duì)列在take的時(shí)候,會(huì)根據(jù)你添加任務(wù)的時(shí)候的時(shí)間做一個(gè)awaitNanos(delay),代碼見該類的take方法。故而實(shí)現(xiàn)了延遲執(zhí)行。

  • Executors.unconfigurableExecutorService

線程池的主要原理是在ThreadPoolExecutor這個(gè)類中。ThreadPoolExecutor有以下概念

  • corePoolSize

  • maximumPoolSize

  • keepAliveTime

  • workQueue

這四個(gè)概念一起解釋,corePoolSize指的是線程池核心數(shù),當(dāng)有任務(wù)進(jìn)來(lái)的時(shí)候,如果開辟的線程少于該值,就不斷開新線程去處理,直到該值。如果到了該值之后,就把新的任務(wù)存放在隊(duì)列中,也就是workQueue中,去存放的過(guò)程會(huì)成功和失敗,如果成功就存放在隊(duì)列中了,如果失敗,就繼續(xù)開辟線程去執(zhí)行。直到線程數(shù)等于maximumPoolSize,便不再開新線程。如果隊(duì)列滿了,線程也到最大值了,這個(gè)時(shí)候,就進(jìn)行拒絕策略。

  • AbortPolicy 默認(rèn)策略,拋出異常RejectedExecutionException。

  • DiscardPolicy 什么都不做

  • DiscardOldestPolicy 把任務(wù)頭丟掉,然后再把任務(wù)加入隊(duì)列

  • CallerRunsPolicy 主線程自己去執(zhí)行任務(wù)

  • RejectHandler 自己實(shí)現(xiàn)

原理大致說(shuō)明。ThreadPoolExecutor這個(gè)類除了參數(shù)那些參數(shù)外,還有HashSet<Worker> workers,參數(shù),該參數(shù)和線程一一對(duì)應(yīng),也就是說(shuō)線程池里面的線程就是worker,當(dāng)任務(wù)進(jìn)來(lái)后會(huì)和corePoolSize比較,繼而新建或者申請(qǐng)worker。新建的線程會(huì)不斷的從任務(wù)隊(duì)列去拿任務(wù),拿任務(wù)有超時(shí)時(shí)間,就是剛才說(shuō)到的keepAliveTime,到達(dá)時(shí)間后,如果說(shuō)當(dāng)前線程數(shù)大于corePollSize,則自己退出該線程。沒(méi)有大于則繼續(xù)循環(huán)運(yùn)行,繼續(xù)循環(huán)運(yùn)行就是在死循環(huán)中去拿隊(duì)列。

第三方中間件的線程池特點(diǎn)

tomcat線程池

tomcat的線程池是StandardThreadExecutor類,該類的屬性也是ThreadPoolExecutor,不過(guò)是把ThreadPoolExecutor動(dòng)態(tài)設(shè)置參數(shù)暴露出來(lái)了。所以StandardThreadExecutor類可以動(dòng)態(tài)的修改核心數(shù),最大數(shù)。并且該類的阻塞隊(duì)列使用的是繼承自LinkedBlockingQueue的TaskQueue。TaskQueue的核心在于,只要運(yùn)行當(dāng)前池子的線程小于maximumPoolSize,就拒絕你加入隊(duì)列。我們知道線程的數(shù)量和IO密集有關(guān)系,tomcat這種IO密集型的中間件,適合更多的線程。這里的線程數(shù)是maxThreads,該值默認(rèn)200,tomcat可以配置。

public boolean offer(Runnable o) {
       //這個(gè)類是TaskQueue的的方法,我們知道,線程池,是先加入隊(duì)列,失敗后再開線程直到max數(shù)。
        if (parent==null) return super.offer(o);
        // 若運(yùn)行線程為最大線程數(shù),說(shuō)明線程已經(jīng)最大了,沒(méi)辦法,還是扔隊(duì)列吧。
        if (parent.getPoolSize() == parent.getMaximumPoolSize()) return super.offer(o);
        //若任務(wù)數(shù)小于線程數(shù),直接扔隊(duì)列,扔隊(duì)列后,那些閑著的線程自然會(huì)取。沒(méi)必要返回false,讓其再重開線程。
        if (parent.getSubmittedCount()<(parent.getPoolSize())) return super.offer(o);
        // 發(fā)現(xiàn)運(yùn)行線程數(shù)少于池最大線程數(shù),拒絕加入隊(duì)列,讓線程池繼續(xù)開線程。
        if (parent.getPoolSize()<parent.getMaximumPoolSize()) return false;
        //if we reached here, we need to add it to the queue
        return super.offer(o);
    }

quartz線程池

quartz線程池是在org.quartz.simpl.SimpleThreadPool

該線程池非常簡(jiǎn)單,初始化的時(shí)候新建N個(gè)線程。這個(gè)線程是在線程池初始化的時(shí)候就新建。然后把線程放在availWorkers中,如果有任務(wù)進(jìn)來(lái),就從availWorkers拿出1個(gè)線程放進(jìn)busyWorkers,然后把任務(wù)給該線程執(zhí)行。執(zhí)行完了之后返回給availWorkers中。如果線程滿了,主線程扔任務(wù)的時(shí)候,會(huì)檢查availWorkers的size,當(dāng)size<1的時(shí)候,停半秒繼續(xù)檢查availWorkers直到有可用才運(yùn)行任務(wù)。

線程池展望

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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