寫在前面
本文是我自己對ThreadPoolExecutor的簡單理解,是看了ThreadPoolExecutor的源碼和orcle官網的文檔之後的體會,並不是一板一眼的翻譯官網,也建議大家結合學習。
如果有誤,歡迎大家批評指正哈~
官網網址
Java™ Platform Standard Ed. 8 Class ThreadPoolExecutor
線程池ThreadPoolExecutor解決的問題:
提高大量同步任務的執行性能;
維護一些基本的數據,比如已完成的任務數
參數:
1.corePoolSize & maximumPoolSize
- 當前線程數少於cirePoolSize,一定會開新的線程。
- 當前線程數大於corePoolSize,少於maximumOiikSuze,只有在隊列曼聯的時候纔會開新的線程。
- 一般是構建的時候初始化,但是可以通過set方法動態更改。
2.預先啓動核心線程池的方法
prestartAllCoreThreads(),prestartAllCoreThreads()
3.生存時間
若當前線程數超過了核心線程池的線程數,多餘的線程會被terminated掉
4.隊列
任何類,只要實現了BlockingQueue接口,就能被用來傳輸和持有提交的任務。該隊列與線程池的規模有關:
- 如果當前運行的線程數<corePoolSize,線程被創建,不放入隊列
- 如果當前運行的線程數>=corePoolSize,線程被放入隊列
- 如果當前運行加入會使得總線程數>maximumPoolSize,任務被拒絕
實現了BlockingQueue的類
( 注意:根據阿里編程規範:不建議用Executors.newFixedThreadPool()、Executors.newCachedThreadPool()和Executors.newSingleThreadExecutor(),建議new ThreadPoolExecutor(…),因爲Executors的幾個方法都是對ThreadPoolExecutor進行了封裝,一個好的程序員應該瞭解其底層實現呦):
1. SynchronousQueue:
- 該隊列不保留任何任務,統統直接扔給線程。要是線程池的線程個數超maximumPoolSize了,就拒絕任務。
- Executors.newCachedThreadPool()就用的這個。所以java編程思想p657裏會說:newCachedThreadPool通常會創建與所需數量相同的線程。在newCachedThreadPool的實現中,maximumPoolSize=Interger.MAX_VALUE,可以看成允許創建無限長的線程啦
- Executors.newCachedThreadPool()缺點是:當提交的任務過多的時候,會創建大量的線程,導致OOM/
2. LinkedBlockingQueue:
- 如果不預定義容量,該隊列會建立一個無限長的隊列(其實長度是Interger.MAX_VALUE,可以看成無限長啦)。
- 任務什麼情況下會被放入隊列裏呢?當運行的任務數>corePoolSize時,就會被放入。而因爲這個隊列是無限長的,所以maximumPoolSize屬性不起任何作用了。
- 所以我們看一下newFixedThreadPool的實現:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
- Executors.newFixedThreadPool()和Executors.newSingleThreadExecutor()就用的這個,適用於類似網頁訪問這種,訪問量可能大到無法估計的情況。使用該方法定義的線程池,運行的線程數是固定的。
3. ArrayBlockingQueue:
看不下去了