更新時間:2020-11-16 17:36:42 來源:動力節(jié)點(diǎn) 瀏覽4193次
線程是一種寶貴的資源,也是一種有限的資源,創(chuàng)建和銷毀線程需要付出不菲的代價。這時候就要用到線程池了,線程池維護(hù)著多個線程,等待著監(jiān)督管理者分配可并發(fā)執(zhí)行的任務(wù)。這避免了在處理短時間任務(wù)時創(chuàng)建與銷毀線程的代價。本文我們就一起來深入學(xué)習(xí)線程池工作流程。
線程池工作流程可以拆分成以下幾個部分:
當(dāng)向線程池提交一個新的任務(wù)時,線程池有三種處理情況,分別是:創(chuàng)建一個工作線程來執(zhí)行該任務(wù)、將任務(wù)加入阻塞隊(duì)列、拒絕該任務(wù)。提交任務(wù)的過程也可以拆分成以下幾個部分:當(dāng)工作線程數(shù)小于核心線程數(shù)時,直接創(chuàng)建新的核心工作線程當(dāng)工作線程數(shù)不小于核心線程數(shù)時,就需要嘗試將任務(wù)添加到阻塞隊(duì)列中去如果能夠加入成功,說明隊(duì)列還沒有滿,那么需要做以下的二次驗(yàn)證來保證添加進(jìn)去的任務(wù)能夠成功被執(zhí)行驗(yàn)證當(dāng)前線程池的運(yùn)行狀態(tài),如果是非RUNNING狀態(tài),則需要將任務(wù)從阻塞隊(duì)列中移除,然后拒絕該任務(wù)驗(yàn)證當(dāng)前線程池中的工作線程的個數(shù),如果為0,則需要主動添加一個空工作線程來執(zhí)行剛剛添加到阻塞隊(duì)列中的任務(wù)如果加入失敗,則說明隊(duì)列已經(jīng)滿了,那么這時就需要創(chuàng)建新的“臨時”工作線程來執(zhí)行任務(wù)如果創(chuàng)建成功,則直接執(zhí)行該任務(wù)如果創(chuàng)建失敗,則說明工作線程數(shù)已經(jīng)等于最大線程數(shù)了,則只能拒絕該任務(wù)了。
創(chuàng)建工作線程需要做一系列的判斷,需要確保當(dāng)前線程池可以創(chuàng)建新的線程之后,才能創(chuàng)建。首先,當(dāng)線程池的狀態(tài)是 SHUTDOWN 或者 STOP 時,則不能創(chuàng)建新的線程。另外,當(dāng)線程工廠創(chuàng)建線程失敗時,也不能創(chuàng)建新的線程。還有就是當(dāng)前工作線程的數(shù)量與核心線程數(shù)、最大線程數(shù)進(jìn)行比較,如果前者大于后者的話,也不允許創(chuàng)建。除此之外,會嘗試通過 CAS 來自增工作線程的個數(shù),如果自增成功了,則會創(chuàng)建新的工作線程,即 Worker 對象。然后加鎖進(jìn)行二次驗(yàn)證是否能夠創(chuàng)建工作線程,最后如果創(chuàng)建成功,則會啟動該工作線程。
當(dāng)工作線程創(chuàng)建成功后,也就是 Worker 對象已經(jīng)創(chuàng)建好了,這時就需要啟動該工作線程,讓線程開始干活了,Worker 對象中關(guān)聯(lián)著一個 Thread,所以要啟動工作線程的話,只要通過 worker.thread.start() 來啟動該線程即可。啟動完了之后,就會執(zhí)行 Worker 對象的 run 方法,因?yàn)?Worker 實(shí)現(xiàn)了 Runnable 接口,所以本質(zhì)上 Worker 也是一個線程。通過線程 start 開啟之后就會調(diào)用到 Runnable 的 run 方法,在 worker 對象的 run 方法中,調(diào)用了 runWorker(this) 方法,也就是把當(dāng)前對象傳遞給了 runWorker 方法,讓他來執(zhí)行。
在 runWorker 方法被調(diào)用之后,就是執(zhí)行具體的任務(wù)了,首先需要拿到一個可以執(zhí)行的任務(wù),而 Worker 對象中默認(rèn)綁定了一個任務(wù),如果該任務(wù)不為空的話,那么就是直接執(zhí)行。執(zhí)行完了之后,就會去阻塞隊(duì)列中獲取任務(wù)來執(zhí)行,而獲取任務(wù)的過程,需要考慮當(dāng)前工作線程的個數(shù)。如果工作線程數(shù)大于核心線程數(shù),那么就需要通過 poll 來獲取,因?yàn)檫@時需要對閑置的線程進(jìn)行回收;如果工作線程數(shù)小于等于核心線程數(shù),那么就可以通過 take 來獲取了,因此這時所有的線程都是核心線程,不需要進(jìn)行回收,前提是沒有設(shè)置 allowCoreThreadTimeOut。
以上就是整個線程池工作流程,我們對每個線程池工作步驟都進(jìn)行了詳細(xì)的講解,為了加深對線程池的理解可以觀看本的多線程教程,深入學(xué)習(xí)更多的還沒有掌握的線程池知識。

初級 202925

初級 203221

初級 202629

初級 203743