您好,登錄后才能下訂單哦!
如何進(jìn)行線程池配置與數(shù)據(jù)庫(kù)連接池最大連接數(shù)配置,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。
線程池 相關(guān)配置,不僅平時(shí)經(jīng)常用到,而且面試也會(huì)經(jīng)常問到。
CPU 密集型任務(wù):這種任務(wù)消耗的主要是 CPU 資源,可以將線程數(shù)設(shè)置為 N(CPU 核心數(shù))+1,比 CPU 核心數(shù)多出來的一個(gè)線程是為了防止線程偶發(fā)的缺頁(yè)中斷,或者其它原因?qū)е碌娜蝿?wù)暫停而帶來的影響。一旦任務(wù)暫停,CPU 就會(huì)處于空閑狀態(tài),而在這種情況下多出來的一個(gè)線程就可以充分利用 CPU 的空閑時(shí)間。
I/O 密集型任務(wù):這種任務(wù)應(yīng)用起來,系統(tǒng)會(huì)用大部分的時(shí)間來處理 I/O 交互,而線程在處理 I/O 的時(shí)間段內(nèi)不會(huì)占用 CPU 來處理,這時(shí)就可以將 CPU 交出給其它線程使用。因此在 I/O 密集型任務(wù)的應(yīng)用中,我們可以多配置一些線程,具體的計(jì)算方法是 2N。
綜上可知:當(dāng)線程數(shù)量太小,同一時(shí)間大量請(qǐng)求將被阻塞在線程隊(duì)列中排隊(duì)等待執(zhí)行線程,此時(shí) CPU 沒有得到充分利用;當(dāng)線程數(shù)量太大,被創(chuàng)建的執(zhí)行線程同時(shí)在爭(zhēng)取 CPU 資源,又會(huì)導(dǎo)致大量的上下文切換,從而增加線程的執(zhí)行時(shí)間,影響了整體執(zhí)行效率。通過測(cè)試可知,4~6 個(gè)線程數(shù)是最合適的。
public ThreadPoolExecutor(int corePoolSize,//線程池的核心線程數(shù)量 int maximumPoolSize,//線程池的最大線程數(shù) long keepAliveTime,//當(dāng)線程數(shù)大于核心線程數(shù)時(shí),多余的空閑線程存活的最長(zhǎng)時(shí)間 TimeUnit unit,//時(shí)間單位 BlockingQueue<Runnable> workQueue,//任務(wù)隊(duì)列,用來儲(chǔ)存等待執(zhí)行任務(wù)的隊(duì)列 ThreadFactory threadFactory,//線程工廠,用來創(chuàng)建線程,一般默認(rèn)即可 RejectedExecutionHandler handler) //拒絕策略,當(dāng)提交的任務(wù)過多而不能及時(shí)處理時(shí),我們可以定制策略來處理任務(wù)
但是某些號(hào)稱XXX架構(gòu)師配置線程池參數(shù)(或者jdbc連接池?cái)?shù)量)還是會(huì)拍腦袋,隨便定個(gè) 核心線程數(shù)或者最大線程數(shù)100
這就是沒有性能意思的碼農(nóng)(估計(jì)都了解過怎么配置,就是沒有在意)了。 雖然說配置比如 最大線程數(shù)100 , 其實(shí)對(duì)于并發(fā)量不大的項(xiàng)目來說,其實(shí)運(yùn)行起來也不會(huì)出什么問題。但是 能改則改。
// CPU 核心數(shù):// 核數(shù) 。 CPU 密集計(jì)算: N+1// IO 類型的就是: 2Nint cores = Runtime.getRuntime().availableProcessors();
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; /** * 自定義異步線程的執(zhí)行器 * 使用 ThreadPoolTaskExecutor 線程池方式,避免開啟過多的線程 * * @author James * @date 2018/7/16 上午11:40 */ @Configuration @EnableAsync public class ExecutorConfig { /** * Set the ThreadPoolExecutor's core pool size. */ private int corePoolSize = 4; /** * Set the ThreadPoolExecutor's maximum pool size. */ private int maxPoolSize = Runtime.getRuntime().availableProcessors() + 3; /** * Set the capacity for the ThreadPoolExecutor's BlockingQueue. * 隊(duì)列數(shù)不能太大,否則就會(huì)任務(wù)堆積,處理就太慢了。 */ private int queueCapacity = 300; @Bean public Executor myAsync() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.setThreadNamePrefix("MyExecutor-"); // rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時(shí)候,如何處理新任務(wù) // CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是有調(diào)用者所在的線程來執(zhí)行 。 一般這種任務(wù)不能丟棄 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } }
以上代碼就是 當(dāng)spring boot 中 執(zhí)行 異步 代碼的時(shí)候所用到的線程池配置了: 即加了 @Async 的方法
使用 LinkedBlockingQueue 是因?yàn)槠淇梢杂懈叩耐掏铝?/p>
import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.util.concurrent.*; @Component public class ExecutionResultPool { private static final Logger logger = LoggerFactory.getLogger(ExecutionResultPool.class); private ExecutorService threadPool; public void init() { // 核數(shù) 。 CPU 密集計(jì)算: N+1 // IO 類型的就是: 2N int cores = Runtime.getRuntime().availableProcessors(); ThreadFactory threadFactory = new ThreadFactoryBuilder() .setNameFormat("timing-executor-pool-%d").build(); threadPool = new ThreadPoolExecutor(4, cores+3, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000), threadFactory, (r, executor) -> { try { // // 嘗試再次加入隊(duì)列。如果隊(duì)列已滿,那么等待,直到隊(duì)列空了就放進(jìn)去 executor.getQueue().put(r); } catch (InterruptedException e) { logger.error("任務(wù)加入隊(duì)列失敗", e); Thread.currentThread().interrupt(); } }); logger.info("初始化任務(wù)執(zhí)行線程池 {}", threadFactory); } public void execute(Runnable runnable) { threadPool.execute(runnable); } }
關(guān)于如何進(jìn)行線程池配置與數(shù)據(jù)庫(kù)連接池最大連接數(shù)配置問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。