<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
ThreadPoolExecutor
是一個實現ExecutorService
介面的執行緒池,ExecutorService
是主要用來處理多執行緒任務的一個介面,通常比較簡單是用法是由Executors
工廠類去建立。
執行緒池主要解決了兩個不同的問題:
ThreadPoolExecutor
提供了幾個核心引數,方便開發人員根據具體場景合理分配執行緒資源。
corePoolSize
:核心執行緒數,線上程池建立時就已初始化好的n個核心執行緒,即使執行緒空閒著也會一直保留線上程池中不被銷燬,除非呼叫執行緒池方法設定了java.util.concurrent.ThreadPoolExecutor#allowCoreThreadTimeOut(true)
(允許核心執行緒超時銷燬)。maximumPoolSize
:執行緒池允許存在最大執行緒數。keepAliveTime
:當執行緒數大於核心執行緒數時,多餘的執行緒在執行任務結束後等待新任務的最大等待時間。unit
:TimeUnit
型別,是keepAliveTime
多餘執行緒最大空餘時間單位。workQueue
:必須指定一個阻塞佇列,線上程池執行execute
方法時新進來的任務在執行前都會保留到此佇列裡進入等待。threadFactory
:建立執行緒的工廠,預設採用Executors.defaultThreadFactory()
建立執行緒。handler
:拒絕策略,當最大執行緒數已佔滿,且佇列已滿,此時執行緒池將觸發拒絕策略,對新進來的任務做拒絕處理,具體的處理方案在後面詳細分析(預設使用java.util.concurrent.ThreadPoolExecutor.AbortPolicy
直接丟擲異常拒絕處理)。注:
maximumPoolSize
如果大於corePoolSize
,則多出的部分執行緒數只有在阻塞佇列workQueue佔滿時才會建立核心執行緒之外的執行緒去執行任務,如果我們設定的阻塞佇列為無界佇列(預設大小為Integer.MAX_VALUE
),則佇列永遠無法佔滿,就不會去建立額外的執行緒進行工作,一般情況如果任務數足夠,那麼也是在佇列大小還沒達到Integer.MAX_VALUE
時就已經出現記憶體溢位了。Executors
執行緒池工廠中的newFixedThreadPool()、newSingleThreadExecutor()
方法就是使用了無界佇列LinkedBlockingQueue
,防止記憶體溢位在日常開發過程中一般是不建議直接去使用Executors
去建立執行緒池。
上面我們提到的可以使用Executors
工廠直接建立執行緒池,但是Executors
提供的建立執行緒池都是不可控的,我們還是得按自己的業務做好分析自定義一個執行緒池。
以下是執行緒池建立的一個案例:
@Slf4j @Configuration public class ThreadPoolConfig { @Value("${threadPool.corePoolSize:8}") private int corePoolSize; @Value("${threadPool.maximumPoolSize:16}") private int maximumPoolSize; @Value("${threadPool.keepAliveTime:60}") private int keepAliveTime; @Value("${threadPool.queueSize:99999}") private int queueSize; @Bean public ThreadPoolExecutor testExecutor() { LinkedBlockingQueue queue = new LinkedBlockingQueue(queueSize); return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, queue, getThreadFactory(), getRejectedExecutionHandler()); } /** * 自定義執行緒池建立執行緒工廠,用於執行緒池建立執行緒的工廠 * @return */ private ThreadFactory getThreadFactory() { return new ThreadFactory() { @Override public Thread newThread(Runnable r) { log.info("===> Create new thread ..."); return new Thread(r); } }; } /** * 自定義拒絕策略,繼續往佇列裡新增任務進入等待 * @return */ private RejectedExecutionHandler getRejectedExecutionHandler() { return new RejectedExecutionHandler() { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // 繼續往佇列裡新增任務,這裡只是一個案例,這種方式並不友好,會丟擲佇列已滿的異常 log.info("===> Handler runnable ......"); executor.getQueue().add(r); } }; } }
application.properties
組態檔
threadPool: corePoolSize: 8 maximumPoolSize: 16 keepAliveTime: 60 # 為方便測試這裡我們設定佇列數小一點 queueSize: 99
由以上的執行緒池設定,我們寫一個demo測試一下:
擷取部分執行紀錄檔:
largestPoolSize=11
,這是由於我們設定的maximumPoolSize=16 > corePoolSize=8
,我們demo執行的是110個任務並行,佇列大小是99,由此分析得出(需要額外出建立執行緒數 = 並行任務總數110 - 核心執行緒數8 - 佇列大小99 = 3),所以執行緒池在佇列已滿時會多建立3個執行緒用於執行任務,在達到keepAliveTime
設定的最大空閒時間後這3個執行緒即會自動銷燬。注:可能有的同學會想執行緒池使用後需要銷燬嗎?在這裡補充一下,如果我們是作為區域性變數建立出來的執行緒池(如:在執行的方法內使用
Executors.newFixedThreadPool(10)
建立臨時的執行緒池),這種情況我們用完就必須將它立即銷燬,否則主執行緒就會一直處於執行狀態。如果是全域性設定的執行緒池,那麼就是為整個系統中諸多業務提供使用的,這種就不需要對執行緒池做銷燬,因為一旦銷燬了其他的任務就無法繼續使用該執行緒池執行任務。
shutdown()
:此方法對執行緒池做銷燬,執行緒池會優先將剩餘未完成的任務執行完才會執行銷燬任務。shutdownNow()
:此方法會對執行緒池做立即銷燬,無論執行緒池中的任務是否執行完成。通常我們在設定好有限佇列大小後,就會有可能出現佇列佔滿的情況,這時候我們的拒絕策略就會起到作用,接下來我們就來分析一下RejectedExecutionHandler
介面具體有哪一些實現方式:
ThreadPoolExecutor
執行緒池中有一個預設執行緒池變數private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
作為預設拒絕策略,檢視如下圖原始碼可知它就是直接丟擲RejectedExecutionException
異常,並且會直接丟棄當前任務,如果擔心異常影響後續任務執行開發人員需自行捕獲例外處理。private RejectedExecutionHandler getRejectedExecutionHandler() { return new RejectedExecutionHandler() { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // 虛擬碼 log.info("===> 可根據任務的重要性區分對待,將任務做轉換入庫延遲處理 ......"); } }; }
執行緒池是為了充分利用CPU資源,在合理分批使用的情況下能夠極大的提高我們程式的效能,以上的引數設定僅作為參考,並沒有一個標準的依據,只能在實際開發過程中開發人員自行多做一些測試來判斷引數如何設定更加合理。
在拒絕策略設定方面,如果被拒絕的任務相對緊急且重要不可丟棄的情況下,此類任務可獨立做一個執行緒池處理保證任務不丟失,程式只能慢慢優化變得越來越好,不可能有完美的程式即保證高效能又保證安全可靠。
到此這篇關於Java執行緒池ThreadPoolExecutor的文章就介紹到這了,更多相關Java執行緒池ThreadPoolExecutor內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45