Java經過Executors提供四種線程池,分別爲:
newCachedThreadPool建立一個可緩存線程池,若是線程池長度超過處理須要,可靈活回收空閒線程,若無可回收,則新建線程。
newFixedThreadPool 建立一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
newScheduledThreadPool 建立一個定長線程池,支持定時及週期性任務執行。
newSingleThreadExecutor 建立一個單線程化的線程池,它只會用惟一的工做線程來執行任務,保證全部任務按照指定順序(FIFO, LIFO, 優先級)執行。算法
熟悉這四種線程池,首先 先了解ThreadPoolExecutor緩存
ThreadPoolExecutor中定義瞭如下幾個屬性比較重要併發
corePoolSize:線程池中的線程數量,線程池中默認開啓幾個線程處理 任務隊列中的任務函數
(注:這個並非固定的,根據隊列(workQueue)的不一樣實現類型而改變)spa
maximumPoolSize:線程池中的最大線程數量,這個屬性感受和上面的corePoolSize衝突,明明上面定義了線程數據了,怎麼這裏又控制了線程
最大線程數量,其實 同樣和 上面提到的同樣(根據隊列(workQueue)的不一樣實現類型 ,須要用到該屬性進行相應的 任務拒絕策略)code
keepAliveTime;//超過corePoolSize的空閒線程,在多長時間內會被銷燬
TimeUnit unit;//keepAliveTime的單位
BlockingQueue<Runnable> workQueue:任務隊列,被提交的但還沒有被執行的任務blog
主要有如下幾種實現類型接口
SynchronousQueue:直接提交的隊列,該隊列沒有容量,每個擦入操做都要對應一個相應的刪除操做,反之每一個刪除操做對應相應的插入操做。隊列
SynchronousQueue不保存任務,它老是將任務提交給線程執行,若是沒有空閒的進程,則嘗試建立新的進程,若是進程
已達到maximumPoolSize設置的最大線程數,則執行拒絕策略
ArrayBlockingQueue:有界任務隊列,ArrayBlockingQueue的構造函數必須帶一個容量參數(例如n),表示該隊列的最大容量。
當有新任務執行時,這個定義當前線程數爲t,構造函數的容量參數爲n,當前隊列長度爲l
1.t<corePoolSize時,建立新的線程之心
2.t>corePoolSize且l<n時,插入到任務隊列,等待空閒線程執行
3.t>corePoolSize且l>=n時,建立新的線程執行新任務
4.t>maximumPoolSize時,執行拒絕策略。
LinkedBlockingQueue:無界任務隊列,當有新任務執行時,若是線程池中線程數小於corePoolSize則建立新的線程,不然進入隊列等待。
若是沒有任務建立速度和處理速度差別很大,無界隊列會保持快速增加,直到耗盡系統內存
PriorityBlockingQueue:優先級隊列,能夠控制任務的執行前後順序,是一個特殊的無界隊列。不管有界的隊列無界的隊列,都是按照先進先出算法
處理任務(絮叨),而該隊列破例能夠根據任務自身的優先級順序前後執行。
ThreadFactory threadFactory//線程工廠,用於建立線程,通常默認
RejectedExecutionHandler handler;//拒絕策略,當任務太多來不及處理,如何拒絕任務
JDK內置的拒絕策略以下:
AbortPolity策略:該策略會直接拋出異常,阻止系統正常工做
CallerRunsPolity策略:只要線程爲關閉,該策略直接在調用者線程中,運行當前被丟棄的任務
DiscardOledstPolicy策略:該策略將丟棄最老的一個請求,也就是即將被執行的一個任務,並嘗試再次提交當前任務。
DiscardPlicy 策略:該策略默默的丟棄沒法處理的任務,不予任務處理。
若是以上策略不能知足實際應用需求,能夠擴展RejectedExecutionHandler 接口
public interface RejectedExecutionHandler { void rejectedExecution(Runnable r, ThreadPoolExecutor executor); }
其中,r爲請求執行的任務,executor爲當前線程池。
瞭解了ThreadPoolExecutor的上述屬性,而後分析Executors提供四種線程池就很簡單了
Executors.newFixedThreadPool(nThreads)
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
返回了一個corePoolSize, maximumPoolSize大小相等而且使用了LinkedBlockingQueue任務隊列的線程池,由於對於固定大小的線程池而言,不存在線程數量的動態
變化,所以corePoolSize,和maximumPoolSize能夠相等,同時它使用無界隊列存放沒法當即執行的任務,當任務提交很是頻繁的時候,該隊列可能迅速膨脹,從而耗盡
系統資源。
Executors.newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
返回單線程的線程池,是newFixedThreadPool()方法的一種退化,只是簡單的將線程池的線程數量設置爲1
Executors.newCachedThreadPool()
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
返回corePoolSize爲0 maximumPoolSize無窮大的線程池,這意味着在沒有任務時,該線程內無線程,而當任務被提交時,該線程池會使用空閒的線程執行任務,若無空閒
線程,則將任務加入SynchronousQueue隊列,而SynchronousQueue隊列是一種直接提交的隊列,它總會迫使線程池增長新的線程執行任務,當任務執行完畢後,
因爲corePoolSize爲0,所以空線程又會在指定時間內(60s)被回收。
對於newCachedThreadPool(),若是同時又大量任務被提交,而任務的執行又不那麼快時,那麼系統便會開啓等量的線程處理,這樣的作法可能會很快耗盡系統的資源。