Java中的ThreadPoolExecutor, 一般使用時直接利用現有的構造工具java.util.concurrent.Executors 直接構造使用, 但是在數據量任務數較多,或者想控制任務執行的時候, 會有一些不方便.
使用ThreadPoolExecutor直接構造我們需要的線程池, 以構造函數
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
爲例,
corePoolSize: 指定核心線程池大小, 需要注意的是, 構造完成後的線程池, 在未接收到任務時, 線程數爲0.
maximumPoolSize: 線程池的最大同時工作線程數, 是否真正生效和後面的workQueue參數設定有直接關係
keepAliveTime: 線程池中 maximumPoolSize減去 corePoolSize的線程在空閒時間的生存時間, 多餘改時間將被銷燬.
unit: 空閒線程的銷燬時間的時間單位
workQueue: 線程池添加的任務在線程池中工作線程數量達到最大設定值後的唯一去處, 未達到最大數量時, 會生成新的工作線程接受任務.
handler: 這個是拒絕策略,後面說.
以如下設置爲例:
LinkedBlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<Runnable>(16);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 100,
20, TimeUnit.MILLISECONDS, blockingQueue,new ThreadPoolExecutor.CallerRunsPolicy());
構造最大容量爲16的queue, 構造核心爲2, 最大爲100, 最長空閒時間爲20ms, 以ThreadPoolExecutor.CallerRunsPolicy爲拒絕策略的線程池.
假設現在有18個任務同時放到該線程池中, 每個任務執行時間爲2s, 那麼執行完大概需要多久?
是的, 需要18s, 因爲核心工作線程爲2, 同時執行兩個任務, 共18個, 需要執行9組, 每組2s, 共計18s, 電腦實際耗時爲 18005ms.
假設現在有100個任務, 需要多久?
小於18s, 因爲線程池首先接收到的任務, 構造了兩個核心工作線程, 緊接着的16個放到queue中, 接下來的task由於queue已滿, 故需要根據maximumPoolSize 擴展線程池中的工作線程, 本例中上限爲100, 故可以擴展98個工作線程, 現有82個task需要加入, 故線程池放完全部100個任務後, 是84個工作線程, 此時queue中還有16個等待任務, 故執行時間大概爲4s, 我電腦實際執行爲4016ms.
任務多了反而更快, 是因爲線程池中的工作線程擴展了, 幹活的多了.
我們線程池最大能容納120個任務,如果我們添加130個任務, 根據我們的拒絕策略, 在線程池未關閉的情況下,將有我們的主線程執行, ThreadPoolExecutor 默認是拒絕新的任務加入.