人人妻人人澡人人爽人人精品av_精品乱码一区内射人妻无码_老司机午夜福利视频_精品成品国色天香摄像头_99精品福利国产在线导航_野花社区在线观看视频_大地资源在线影视播放_东北高大肥胖丰满熟女_金门瓶马车内剧烈运动

首頁(yè)>國(guó)內(nèi) > 正文

我們一起聊聊并發(fā)編程:線程池

2023-07-11 10:26:21來源:今日頭條

一、線程池的實(shí)現(xiàn)原理

下圖所示為線程池的實(shí)現(xiàn)原理:調(diào)用方不斷地向線程池中提交任務(wù);線程池中有一組線程,不斷地 從隊(duì)列中取任務(wù),這是一個(gè)典型的生產(chǎn)者—消費(fèi)者模型。


【資料圖】

要實(shí)現(xiàn)這樣一個(gè)線程池,有幾個(gè)問題需要考慮:

1. 隊(duì)列設(shè)置多長(zhǎng)?如果是無界的,調(diào)用方不斷地往隊(duì)列中放任務(wù),可能導(dǎo)致內(nèi)存耗盡。如果是有 界的,當(dāng)隊(duì)列滿了之后,調(diào)用方如何處理?

2. 線程池中的線程個(gè)數(shù)是固定的,還是動(dòng)態(tài)變化的?

3. 每次提交新任務(wù),是放入隊(duì)列?還是開新線程?

4. 當(dāng)沒有任務(wù)的時(shí)候,線程是睡眠一小段時(shí)間?還是進(jìn)入阻塞?如果進(jìn)入阻塞,如何喚醒?

針對(duì)問題4,有3種做法:

1. 不使用阻塞隊(duì)列,只使用一般的線程安全的隊(duì)列,也無阻塞/喚醒機(jī)制。當(dāng)隊(duì)列為空時(shí),線程 池中的線程只能睡眠一會(huì)兒,然后醒來去看隊(duì)列中有沒有新任務(wù)到來,如此不斷輪詢。

2. 不使用阻塞隊(duì)列,但在隊(duì)列外部、線程池內(nèi)部實(shí)現(xiàn)了阻塞/喚醒機(jī)制。

3. 使用阻塞隊(duì)列。

很顯然,做法3最完善,既避免了線程池內(nèi)部自己實(shí)現(xiàn)阻塞/喚醒機(jī)制的麻煩,也避免了做法1的睡 眠/輪詢帶來的資源消耗和延遲。正因?yàn)槿绱?,接下來要講的ThreadPoolExector/ScheduledThreadPoolExecutor都是基于阻塞隊(duì)列來實(shí)現(xiàn)的,而不是一般的隊(duì)列, 至此,各式各樣的阻塞隊(duì)列就要派上用場(chǎng)了

二、線程池的類繼承體系

在這里,有兩個(gè)核心的類: ThreadPoolExector 和ScheduledThreadPoolExecutor ,后者不僅 可以執(zhí)行某個(gè)任務(wù),還可以周期性地執(zhí)行任務(wù)。

向線程池中提交的每個(gè)任務(wù),都必須實(shí)現(xiàn) Runnable 接口,通過最上面的 Executor 接口中的 execute(Runnable command) 向線程池提交任務(wù)。

然后,在ExecutorService 中,定義了線程池的關(guān)閉接口 shutdown() ,還定義了可以有返回值 的任務(wù),也就是 Callable ,后面會(huì)詳細(xì)介紹。

三、ThreadPoolExecutor1、核心數(shù)據(jù)結(jié)構(gòu)

基于線程池的實(shí)現(xiàn)原理,下面看一下ThreadPoolExector的核心數(shù)據(jù)結(jié)構(gòu)。

每一個(gè)線程是一個(gè)Worker對(duì)象。Worker是ThreadPoolExector的內(nèi)部類,核心數(shù)據(jù)結(jié)構(gòu)如下:

由定義會(huì)發(fā)現(xiàn),Worker繼承于AQS,也就是說Worker本身就是一把鎖。這把鎖有什么用處呢?用于線程池的關(guān)閉、線程執(zhí)行任務(wù)的過程中。

2、核心配置參數(shù)解釋

ThreadPoolExecutor在其構(gòu)造方法中提供了幾個(gè)核心配置參數(shù),來配置不同策略的線程池。

上面的各個(gè)參數(shù),解釋如下:

1. corePoolSize:在線程池中始終維護(hù)的線程個(gè)數(shù)。

2. maxPoolSize:在corePooSize已滿、隊(duì)列也滿的情況下,擴(kuò)充線程至此值。

3. keepAliveTime/TimeUnit:maxPoolSize 中的空閑線程,銷毀所需要的時(shí)間,總線程數(shù)收縮 回corePoolSize。

4. blockingQueue:線程池所用的隊(duì)列類型。

5. threadFactory:線程創(chuàng)建工廠,可以自定義,有默認(rèn)值Executors.defaultThreadFactory()

6. RejectedExecutionHandler:corePoolSize已滿,隊(duì)列已滿,maxPoolSize 已滿,最后的拒 絕策略。

下面來看這6個(gè)配置參數(shù)在任務(wù)的提交過程中是怎么運(yùn)作的。在每次往線程池中提交任務(wù)的時(shí)候,有 如下的處理流程:

步驟一:判斷當(dāng)前線程數(shù)是否大于或等于corePoolSize。如果小于,則新建線程執(zhí)行;如果大于, 則進(jìn)入步驟二。

步驟二:判斷隊(duì)列是否已滿。如未滿,則放入;如已滿,則進(jìn)入步驟三。

步驟三:判斷當(dāng)前線程數(shù)是否大于或等于maxPoolSize。如果小于,則新建線程執(zhí)行;如果大于, 則進(jìn)入步驟四。

步驟四:根據(jù)拒絕策略,拒絕任務(wù)。

總結(jié)一下:首先判斷corePoolSize,其次判斷blockingQueue是否已滿,接著判斷maxPoolSize, 最后使用拒絕策略。 很顯然,基于這種流程,如果隊(duì)列是無界的,將永遠(yuǎn)沒有機(jī)會(huì)走到步驟三,也即maxPoolSize沒有 使用,也一定不會(huì)走到步驟四。

關(guān)鍵詞:

相關(guān)新聞

Copyright 2015-2020   三好網(wǎng)  版權(quán)所有 聯(lián)系郵箱:435 22 [email protected]  備案號(hào): 京ICP備2022022245號(hào)-21