java線程池合理設(shè)置最大線程數(shù)和核心線程數(shù)方式
線程池合理設(shè)置最大線程數(shù)和核心線程數(shù)
工作中有這樣一個(gè)場(chǎng)景,需要處理千萬級(jí)別的數(shù)據(jù)的一個(gè)算法,大部分是增刪查的操作。這個(gè)時(shí)候就需要使用多線程去處理。
一開始是這么配置的
@Configuration
@EnableAsync(proxyTargetClass = true)//利用@EnableAsync注解開啟異步任務(wù)支持
@ComponentScan({"com.ctfojt.auditbcarslogo.service"}) //必須加此注解掃描包
public class ThreadPoolConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(10);//核心線程大小
taskExecutor.setMaxPoolSize(20);//最大線程大小
taskExecutor.setQueueCapacity(500);//隊(duì)列最大容量
//當(dāng)提交的任務(wù)個(gè)數(shù)大于QueueCapacity,就需要設(shè)置該參數(shù),但spring提供的都不太滿足業(yè)務(wù)場(chǎng)景,可以自定義一個(gè),也可以注意不要超過QueueCapacity即可
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
taskExecutor.setAwaitTerminationSeconds(10);
taskExecutor.setThreadNamePrefix("BCarLogo-Thread-");
taskExecutor.initialize();
return taskExecutor;
}
}
這樣配置效率很低,一天大概能處理30多萬的數(shù)據(jù)。往后隨著插入表的數(shù)據(jù)越來越多,處理速度也隨之降低,跑個(gè)一兩天之后,差不多能夠處理10萬多。完全滿足不了需求。
后來網(wǎng)上查詢線程池核心數(shù)配置
大部分都是這樣的:
注:IO密集型(某大廠實(shí)踐經(jīng)驗(yàn)) 核心線程數(shù) = CPU核數(shù) / (1-阻塞系數(shù))或著 CPU密集型:核心線程數(shù) = CPU核數(shù) + 1 IO密集型:核心線程數(shù) = CPU核數(shù) * 2
也嘗試著這么配置,結(jié)果發(fā)現(xiàn)效率并不理想,提高不了多少。
最后我是這么配置的
結(jié)果效率大大提升,僅用不到一天的數(shù)據(jù),就跑完了千萬級(jí)的數(shù)據(jù)。
//獲取當(dāng)前機(jī)器的核數(shù)
public static final int cpuNum = Runtime.getRuntime().availableProcessors();
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(cpuNum);//核心線程大小
taskExecutor.setMaxPoolSize(cpuNum * 2);//最大線程大小
taskExecutor.setQueueCapacity(500);//隊(duì)列最大容量
//當(dāng)提交的任務(wù)個(gè)數(shù)大于QueueCapacity,就需要設(shè)置該參數(shù),但spring提供的都不太滿足業(yè)務(wù)場(chǎng)景,可以自定義一個(gè),也可以注意不要超過QueueCapacity即可
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
taskExecutor.setAwaitTerminationSeconds(60);
taskExecutor.setThreadNamePrefix("BCarLogo-Thread-");
taskExecutor.initialize();
return taskExecutor;
}
完美的解決了問題!
線程池核心線程數(shù)與最大線程數(shù)的區(qū)別
線程池策略
corePoolSize:核心線程數(shù);maximunPoolSize:最大線程數(shù)
每當(dāng)有新的任務(wù)到線程池時(shí),
- 第一步:先判斷線程池中當(dāng)前線程數(shù)量是否達(dá)到了corePoolSize,若未達(dá)到,則新建線程運(yùn)行此任務(wù),且任務(wù)結(jié)束后將該線程保留在線程池中,不做銷毀處理,若當(dāng)前線程數(shù)量已達(dá)到corePoolSize,則進(jìn)入下一步;
- 第二步:判斷工作隊(duì)列(workQueue)是否已滿,未滿則將新的任務(wù)提交到工作隊(duì)列中,滿了則進(jìn)入下一步;
- 第三步:判斷線程池中的線程數(shù)量是否達(dá)到了maxumunPoolSize,如果未達(dá)到,則新建一個(gè)工作線程來執(zhí)行這個(gè)任務(wù),如果達(dá)到了則使用飽和策略來處理這個(gè)任務(wù)。注意: 在線程池中的線程數(shù)量超過corePoolSize時(shí),每當(dāng)有線程的空閑時(shí)間超過了keepAliveTime,這個(gè)線程就會(huì)被終止。直到線程池中線程的數(shù)量不大于corePoolSize為止。
(由第三步可知,在一般情況下,Java線程池中會(huì)長(zhǎng)期保持corePoolSize個(gè)線程。)
飽和策略
當(dāng)工作隊(duì)列滿且線程個(gè)數(shù)達(dá)到maximunPoolSize后所采取的策略
AbortPolicy:默認(rèn)策略;新任務(wù)提交時(shí)直接拋出未檢查的異常RejectedExecutionException,該異??捎烧{(diào)用者捕獲。CallerRunsPolicy:既不拋棄任務(wù)也不拋出異常,使用調(diào)用者所在線程運(yùn)行新的任務(wù)。DiscardPolicy:丟棄新的任務(wù),且不拋出異常。DiscardOldestPolicy:調(diào)用poll方法丟棄工作隊(duì)列隊(duì)頭的任務(wù),然后嘗試提交新任務(wù)自定義策略:根據(jù)用戶需要定制。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決rocketmq-spring-boot-starter導(dǎo)致的多消費(fèi)者實(shí)例重復(fù)消費(fèi)問題
這篇文章主要介紹了解決rocketmq-spring-boot-starter導(dǎo)致的多消費(fèi)者實(shí)例重復(fù)消費(fèi)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
springboot使用webservice發(fā)布和調(diào)用接口的實(shí)例詳解
本文介紹了如何在Springboot中使用webservice發(fā)布和調(diào)用接口,涵蓋了必要的依賴添加和代碼示例,文中提供了服務(wù)端和客戶端的實(shí)現(xiàn)方法,以及如何設(shè)置端口和服務(wù)地址,幫助讀者更好地理解和應(yīng)用Springboot結(jié)合webservice的技術(shù)2024-10-10
Java異步編程之Callbacks與Futures模型詳解
這篇文章主要為大家詳細(xì)介紹了Java異步編程中Callbacks與Futures模型的使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03
深入探究一下Java中不同的線程間數(shù)據(jù)通信方式
這篇文章主要來和大家一起深入探究一下Java中不同的線程間數(shù)據(jù)通信方式,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下2023-04-04
解決Spring security5.5.7報(bào)錯(cuò)Encoded password does
這篇文章主要介紹了解決Spring security5.5.7出現(xiàn)Encoded password does not look like BCrypt異常問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
詳解SpringBoot如何自定義一個(gè)Starter
小伙伴們?cè)?jīng)可能都經(jīng)歷過整天寫著CURD的業(yè)務(wù),都沒寫過一些組件相關(guān)的東西,這篇文章記錄一下SpringBoot如何自定義一個(gè)Starter。原理和理論就不用多說了,可以在網(wǎng)上找到很多關(guān)于該方面的資料,這里主要分享如何自定義2022-11-11
java 使用idea將工程打成jar并創(chuàng)建成exe文件類型執(zhí)行的方法詳解
這篇文章主要介紹了java 使用idea將工程打成jar并創(chuàng)建成exe文件類型執(zhí)行,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-09-09
SpringBoot將項(xiàng)目打成war包步驟解析
這篇文章主要介紹了SpringBoot將項(xiàng)目打成war包步驟解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03

