下降資源消耗。經過重複利用已建立的線程下降線程建立、銷燬線程形成的消耗。程序員
提升響應速度。當任務到達時,任務能夠不須要等到線程建立就能當即執行。數組
提升線程的可管理性。線程是稀缺資源,若是無限制的建立,不只會消耗系統資源,還會下降系統的穩定性,使用線程池能夠進行統一的分配、調優和監控緩存
參數 | 說明 |
---|---|
corePoolSize | 核心線程數量,線程池維護線程的最少數量 |
maximumPoolSize | 線程池維護線程的最大數量 |
keepAliveTime | 線程池除核心線程外的其餘線程的最長空閒時間,超過該時間的空閒線程會被銷燬 |
unit | keepAliveTime的單位,TimeUnit中的幾個靜態屬性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS |
workQueue | 線程池所使用的任務緩衝隊列 |
threadFactory | 線程工廠,用於建立線程,通常用默認的便可 |
handler | 線程池對拒絕任務的處理策略 |
當線程池任務處理不過來的時候(何時認爲處理不過來後面描述),能夠經過handler指定的策略進行處理,ThreadPoolExecutor提供了四種策略:併發
能夠經過實現RejectedExecutionHandler接口自定義處理方式。函數
2.1. 若是此時線程池中的數量小於corePoolSize,即便線程池中的線程都處於空閒狀態,也要建立新的線程來處理被添加的任務。線程
2.2. 若是此時線程池中的數量等於corePoolSize,可是緩衝隊列workQueue未滿,那麼任務被放入緩衝隊列。code
2.3. 若是此時線程池中的數量大於等於corePoolSize,緩衝隊列workQueue滿,而且線程池中的數量小於maximumPoolSize,建新的線程來處理被添加的任務。對象
2.4. 若是此時線程池中的數量大於corePoolSize,緩衝隊列workQueue滿,而且線程池中的數量等於maximumPoolSize,那麼經過 handler所指定的策略來處理此任務。接口
2.5. 當線程池中的線程數量大於 corePoolSize時,若是某線程空閒時間超過keepAliveTime,線程將被終止。這樣,線程池能夠動態的調整池中的線程數。隊列
總結即:處理任務判斷的優先級爲 核心線程corePoolSize、任務隊列workQueue、最大線程maximumPoolSize,若是三者都滿了,使用handler處理被拒絕的任務。
注意:
3.1. shutdown() 不接收新任務,會處理已添加任務 3.2. shutdownNow() 不接受新任務,不處理已添加任務,中斷正在處理的任務
4.1. ArrayBlockingQueue: 這是一個由數組實現的容量固定的有界阻塞隊列.
4.2. SynchronousQueue: 沒有容量,不能緩存數據;每一個put必須等待一個take; offer()的時候若是沒有另外一個線程在poll()或者take()的話返回false。
4.3. LinkedBlockingQueue: 這是一個由單鏈表實現的默認無界的阻塞隊列。LinkedBlockingQueue提供了一個可選有界的構造函數,而在未指明容量時,容量默認爲Integer.MAX_VALUE。
隊列操做:
方法 | 說明 |
---|---|
add | 增長一個元索; 若是隊列已滿,則拋出一個異常 |
remove | 移除並返回隊列頭部的元素; 若是隊列爲空,則拋出一個異常 |
offer | 添加一個元素並返回true; 若是隊列已滿,則返回false |
poll | 移除並返回隊列頭部的元素; 若是隊列爲空,則返回null |
put | 添加一個元素; 若是隊列滿,則阻塞 |
take | 移除並返回隊列頭部的元素; 若是隊列爲空,則阻塞 |
element | 返回隊列頭部的元素; 若是隊列爲空,則拋出一個異常 |
peek | 返回隊列頭部的元素; 若是隊列爲空,則返回null |
1. Executors.newCachedThreadPool(); 說明: 建立一個可緩存線程池,若是線程池長度超過處理須要,可靈活回收空閒線程,若無可回收,則新建線程. 內部實現:new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<runnable>());</runnable>
2. Executors.newFixedThreadPool(int); 說明: 建立一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。 內部實現:new ThreadPoolExecutor(nThreads, nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<runnable>());</runnable>
3. Executors.newSingleThreadExecutor(); 說明:建立一個單線程化的線程池,它只會用惟一的工做線程來執行任務,保證全部任務按照順序執行。 內部實現:new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<runnable>())</runnable>
4. Executors.newScheduledThreadPool(int); 說明:建立一個定長線程池,支持定時及週期性任務執行。 內部實現:new ScheduledThreadPoolExecutor(corePoolSize)
【附】阿里巴巴Java開發手冊中對線程池的使用規範
public class TimerTaskThread extends Thread { public TimerTaskThread(){ super.setName("TimerTaskThread"); ... } }
【強制】線程資源必須經過線程池提供,不容許在應用中自行顯式建立線程。 說明: 使用線程池的好處是減小在建立和銷燬線程上所花的時間以及系統資源的開銷,解決資 源不足的問題。若是不使用線程池,有可能形成系統建立大量同類線程而致使消耗完內存或者 「過分切換」的問題。
【強制】線程池不容許使用 Executors 去建立,而是經過 ThreadPoolExecutor 的方式,這樣 的處理方式讓寫的同窗更加明確線程池的運行規則,規避資源耗盡的風險。
說明: Executors 返回的線程池對象的弊端以下: 1) FixedThreadPool 和 SingleThreadPool: 容許的請求隊列長度爲 Integer.MAX_VALUE,可能會堆積大量的請求,從而致使 OOM。 2) CachedThreadPool 和 ScheduledThreadPool: 容許的建立線程數量爲 Integer.MAX_VALUE, 可能會建立大量的線程,從而致使 OOM。
ThreadPoolExecutor經過幾個核心參數來定義不一樣類型的線程池,適用於不一樣的使用場景;其中在任務提交時,會依次判斷corePoolSize, workQueque, 及maximumPoolSize,不一樣的狀態不一樣的處理。技術領域水太深,若是不是平常使用,基本一段時間後某些知識點就忘的差很少了,所以階段性地回顧與總結,對夯實本身的技術基礎頗有必要。