在一個應用程序中,需要多次使用線程,也就是需要多次創建並銷燬線程。而創建並銷燬線程的過程勢必會消耗內存。所以便於管理線程,線程池就誕生啦。
ThreadPoolExecutor
ThreadPoolExecutor的構造函數:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize:指定線程池中的線程數量,它的數量決定了添加的任務是開闢新的線程去執行,還是放到workQueue任務隊列中去。
maximumPoolSize:指定線程池中的最大線程數量。
keepAliveTime:當線程池中空閒線程數量超過corePoolSize時,多餘線程會在多長時間內被銷燬。
unit:keepAliveTime的單位
workQueue:任務隊列,被增加到線程池中,但還未被執行的任務。分爲直接提交隊列,有界任務隊列、無界任務隊列、優先人物隊列
threadFactory:線程工廠,用於創建線程
handle:拒絕策略
放張圖來理解下。
一、workQueue任務隊列
1.直接提交隊列: SynchronousQueue,一個特殊的BlockingQueue,提交的任務不會被緩存,每執行一個插入操作就會阻塞,需要再執行一個刪除操作纔會被喚醒。
2.有界的任務隊列: ArrayBlockingQueue,基於數組
3.無界的任務隊列:LinkedBlockingQueue,基於鏈表
4.優先任務隊列:PriorityBlockingQueue,按照優先級進行內部元素排序的無限隊列。
無限隊列就是任務池中的任務隊列可以無限制的增加新的任務,而線程池創建的最大數量就是corePoolSize設置的數量,在這種情況下maximumPoolSize這個參數是無效的。即使任務隊列中緩存了很多未執行的任務,當線程池線程數量達到corePoolSize後就不會增加了。
Blocking:當隊列滿了,便會阻塞等待,直到有元素出隊,後續的元素纔可以被加入隊列。
二、拒絕策略
1.AbortPolicy策略:直接拋出異常,阻止系統正常工作。
2.CallerRunsPolicy:直接調用execute來執行當前任務。
3.DisCardPolicy:不執行新任務,也不拋出異常,不做任何處理。
4.DisCardOldestPolicy:丟棄任務隊列中最老的一個任務,也就是當前任務隊列中最先被添加進去的,馬上要被執行的那個任務,並嘗試再次提交。
三、四種常見的線程池:
1.CachedThreadPool:可緩存的線程池,該線程池中沒有核心線程,非核心線程的數量爲Integer.max_value,就是無限大,當有需要時創建線程來執行任務,沒有需要時回收線程,適用於耗時少,任務量大的情況。
2.SecudleThreadPool:週期性執行任務的線程池,按照某種特定的計劃執行線程中的任務,有核心線程,但也有非核心線程,非核心線程的大小也爲無限大。適用於執行週期性的任務。
3.SingleThreadPool:只有一條線程來執行任務,適用於有順序的任務的應用場景。
4.FixedThreadPool:定長的線程池,有核心線程,核心線程的即爲最大的線程數量,沒有非核心線程。