列舉一個線程池max=6,core=3,任務隊列taskQueue=5;採用飽和策略爲1)
則我們看看提交任務給此線程池的執行邏輯如下:
1)首先我們提交第一個任務到線程池,此時核心線程數都還沒有用,所以會啓動核心線程之一來執行任務
2)接着提交第二個第三個任務到線程池,他們的執行邏輯同第一個任務是一模一樣的,線程池會啓動核心線程池中剩下的兩個線程來執行你新提交的任務。
3)接着又有新的任務提交過來,這個時候線程池發現核心線程池中的線程已經都在工作中,所以會去看任務隊列taskQueue是否滿了,發現並沒有,是空的,所以將這個任務放入任務隊列中等待覈心線程池中有空閒線程時自己來取任務執行。
4)接着又提交了4個任務到線程池,他們分別判斷核心線程是否空閒,不空閒,然後判斷任務隊列是否已滿,不滿,則直接將任務放入隊列;
5)接着新的任務又來,則在判斷核心線程池和任務隊列之後,發現任務依然沒有辦法處理,(max=6,core=3正在執行任務,新來一個線程,3+1<6,此時隊列taskQueue已經滿了,corepoolsize=3也都在幹活)則會判斷是否線程數達到最大,發現沒有,則新啓動線程來執行任務;(新的任務開始加入到執行任務中,3個corepoolsize+1個非核心線程,此時執行任務4,可理解新添加的任務是非核心線程任務在執行任務)
6)接着又來一個任務,執行流程同5,(此時有5個線程在執行任務,2個非核心線程在執行任務,3個corepoolsize在執行任務);
7)接着又來一個任務,執行流程同5,(此時有6個線程在執行任務,3個非核心線程在執行任務,3個corepoolsize在執行任務);
8)再來一個任務,發現核心線程池在忙,任務隊列也滿了,線程池中的全部線程也都在工作(3個corepoolsize+3個非核心線程=max(6)都在工作,如果加入新的線程則3個corepoolsize+4個非核心線程>max(6),將報拒絕異常),沒有辦法處理他了,所以他找到了飽和策略,因爲飽和策略是默認的拋異常,所以線程池會告訴提交任務的線程,已經沒有可以用的線程了。
以上就一個核心線程數是3,總線程數是6,任務隊列長度爲5,默認策略採用拋異常的策略的從最開始到最後線程池滿負荷運作的過程
關注點1 線程池大小
線程池有兩個線程數的設置,一個爲核心池線程數,一個爲最大線程數。
在創建了線程池後,默認情況下,線程池中並沒有任何線程,等到有任務來才創建線程去執行任務,除非調用了prestartAllCoreThreads()或者prestartCoreThread()方法
當創建的線程數等於 corePoolSize 時,會加入設置的阻塞隊列。當隊列滿時,會創建線程執行任務直到線程池中的數量等於maximumPoolSize。
關注點2 適當的阻塞隊列
java.lang.IllegalStateException: Queue full
方法 拋出異常 返回特殊值 一直阻塞 超時退出
插入方法 add(e) offer(e) put(e) offer(e,time,unit)
移除方法 remove() poll() take() poll(time,unit)
檢查方法 element() peek() 不可用 不可用
ArrayBlockingQueue :一個由數組結構組成的有界阻塞隊列。
LinkedBlockingQueue :一個由鏈表結構組成的有界阻塞隊列。
PriorityBlockingQueue :一個支持優先級排序的無界阻塞隊列。
DelayQueue: 一個使用優先級隊列實現的無界阻塞隊列。
SynchronousQueue: 一個不存儲元素的阻塞隊列。
LinkedTransferQueue: 一個由鏈表結構組成的無界阻塞隊列。
LinkedBlockingDeque: 一個由鏈表結構組成的雙向阻塞隊列。
關注點3 明確拒絕策略
ThreadPoolExecutor.AbortPolicy: 丟棄任務並拋出RejectedExecutionException異常。 (默認)
ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不拋出異常。
ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然後重新嘗試執行任務(重複此過程)
ThreadPoolExecutor.CallerRunsPolicy:由調用線程處理該任務
說明:Executors 各個方法的弊端:
1)newFixedThreadPool 和 newSingleThreadExecutor:
主要問題是堆積的請求處理隊列可能會耗費非常大的內存,甚至 OOM。
2)newCachedThreadPool 和 newScheduledThreadPool:
主要問題是線程數最大數是 Integer.MAX_VALUE,可能會創建數量非常多的線程,甚至 OOM。
https://blog.csdn.net/qq_33581278/article/details/84568675