線程池ThreadPoolExecutor參數設置


一、概述

DK1.5中引入了強大的concurrent包,其中最常用的莫過了線程池的實現ThreadPoolExecutor,它給我們帶來了極大的方便,但同時,對於該線程池不恰當的設置也可能使其效率並不能達到預期的效果,甚至僅相當於或低於單線程的效率。

ThreadPoolExecutor類可設置的參數主要有:

corePoolSize
核心線程數,核心線程會一直存活,即使沒有任務需要處理。當線程數小於核心線程數時,即使現有的線程空閑,線程池也會優先創建新線程來處理任務,而不是直接交給現有的線程處理。

核心線程在allowCoreThreadTimeout被設置為true時會超時退出,默認情況下不會退出。

maxPoolSize
當線程數大於或等於核心線程,且任務隊列已滿時,線程池會創建新的線程,直到線程數量達到maxPoolSize。如果線程數已等於maxPoolSize,且任務隊列已滿,則已超出線程池的處理能力,線程池會拒絕處理任務而拋出異常。
keepAliveTime
當線程空閑時間達到keepAliveTime,該線程會退出,直到線程數量等於corePoolSize。如果allowCoreThreadTimeout設置為true,則所有線程均會退出直到線程數量為0。

allowCoreThreadTimeout
是否允許核心線程空閑退出,默認值為false。

queueCapacity
任務隊列容量。從maxPoolSize的描述上可以看出,任務隊列的容量會影響到線程的變化,因此任務隊列的長度也需要恰當的設置。


線程池按以下行為執行任務

當線程數小於核心線程數時,創建線程。
當線程數大於等於核心線程數,且任務隊列未滿時,將任務放入任務隊列。
當線程數大於等於核心線程數,且任務隊列已滿
若線程數小於最大線程數,創建線程
若線程數等於最大線程數,拋出異常,拒絕任務

系統負載

參數的設置跟系統的負載有直接的關系,下面為系統負載的相關參數:

tasks,每秒需要處理的最大任務數量
tasktime,處理第個任務所需要的時間
responsetime,系統允許任務最大的響應時間,比如每個任務的響應時間不得超過2秒。

 

二、詳細參數設置說明

1、默認值 * corePoolSize=1 * queueCapacity=Integer.MAX_VALUE * maxPoolSize=Integer.MAX_VALUE * keepAliveTime=60s * allowCoreThreadTimeout=false * rejectedExecutionHandler=AbortPolicy() 2、如何來設置 * 需要根據幾個值來決定 - tasks :每秒的任務數,假設為500~1000 - taskcost:每個任務花費時間,假設為0.1s - responsetime:系統允許容忍的最大響應時間,假設為1s * 做幾個計算 - corePoolSize = 每秒需要多少個線程處理? * threadcount = tasks/(1/taskcost) =tasks*taskcout = (500~1000)*0.1 = 50~100 個線程。
       corePoolSize設置應該大於50 * 根據8020原則,如果80%的每秒任務數小於800,那么corePoolSize設置為80即可 - queueCapacity = (coreSizePool/taskcost)*responsetime * 計算可得 queueCapacity = 80/0.1*1 = 80。意思是隊列里的線程可以等待1s,超過了的需要新開線程來執行 * 切記不能設置為Integer.MAX_VALUE,這樣隊列會很大,線程數只會保持在corePoolSize大小
      ,當任務陡增時,不能新開線程來執行,響應時間會隨之陡增。 - maxPoolSize = (max(tasks)- queueCapacity)/(1/taskcost) * 計算可得 maxPoolSize = (1000-80)/10 = 92 * (最大任務數-隊列容量)/每個線程每秒處理能力 = 最大線程數 - rejectedExecutionHandler:根據具體情況來決定,任務不重要可丟棄,任務重要則要利用一些緩沖機制來處理 - keepAliveTimeallowCoreThreadTimeout采用默認通常能滿足 3 以上都是理想值,實際情況下要根據機器性能來決定。如果在未達到最大線程數的情況機器cpu load已經滿了
    ,則需要通過升級硬件(呵呵)和優化代碼,降低taskcost來處理。

          4、簡單實例定義

          

// ThreadFactory 兩種定義方式
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNamePrefix("自定義線程-").build();
        ThreadFactory threadFactory1=new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                 Thread thread=  new Thread(r);
                 thread.setName("自定義線程02---");
                 return  thread;
            }
        };

        ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(1,3,100, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());

 

以上關於線程數量的計算並沒有考慮CPU的情況。若結合CPU的情況,比如,當線程數量達到50時,CPU達到100%,則將maxPoolSize設置為60也不合適,此時若系統負載長時間維持在每秒1000個任務,則超出線程池處理能力,應設法降低每個任務的處理時間(tasktime)。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM