【線程池】線程池的4種拒絕策略
線程被拒絕的場景

結合上面的圖,我們思考一個問題,當我們創(chuàng)建一個線程池的時候,他會有最大的線程數,和線程任務緩存數。如果系統的線程任務突然暴增,這個時候,線程池的線程達到最大值,線程隊列中的緩存數也達到了最大值,這個時候,沒有擠進線程池的該怎么辦。
在使用線程池的時候,可能會遇到兩種情況,導致線程會需要被拒絕。
- 調用 shutdown 等方法關閉線程池后,即便此時可能線程池內部依然有沒執(zhí)行完的任務正在執(zhí)行,但是由于線程池已經關閉,此時如果再向線程池內提交任務,就會遭到拒絕。
- 線程池沒有能力繼續(xù)處理新提交的任務,也就是工作已經非常飽和的時候。
線程池的拒絕Handler
其實在這里,我們其實可以想到線程池的初始配置中有一個配置handler,這個其實就是為了解決這種問題而出現的,在線程池中,除了我們自己可以定義一個拒絕Handler策略,線程池其實也內置了四種不同的拒絕策略供我們使用。
線程策略
AbortPolicy(異常策略)
在遇到拒絕任務時,會直接拋出一個類型為 RejectedExecutionException 的 RuntimeException,所以我會叫他為異常策略,因為他會拋出異常。這個異常你可以捕獲起來,然后做你想做的事。
DiscardPolicy(丟棄策略)
這個策略就比較悲傷了,當線程滿了之后,后面想進來的線程會被直接丟棄掉,丟棄掉的線程后面不會再執(zhí)行,也不會有通知,更不會有記錄,所以這個策略比較危險,他會讓線程人間蒸發(fā)。這樣大家都不知道他有沒有發(fā)生過。如果發(fā)生在業(yè)務上,可能會造成業(yè)務數據的丟失。
DiscardOldestPolicy (犧牲策略)
這個就比較殘忍,雖然不會丟棄掉想要擠進來的線程,但是他會把線程隊列中存活時間久的線程給丟棄掉,讓想擠進來的線程去替代他。有點像渣男。可以把它叫為渣男策略
CallerRunsPolicy(執(zhí)行策略)
這個策略就比較負責了,當線程池滿了之后,想要進來的線程不會被丟棄,他會直接讓提交線程的線程去執(zhí)行這個線程任務,也是不進入到線程池,你直接就地解決吧。更簡單的理解為,當遇到了這個策略,相當于這個線程池新增了一個線程資源。
這樣的方式有兩點好處
- 新提交的任務不會被丟棄,也就不會造成業(yè)務上的損失。
- 新提交的任務會讓提交者的線程去執(zhí)行,這個時候提交者的線程就會被阻塞一段時間,這段時間其實會給線程池減少一定程度的壓力,減緩了提交者的去提交線程的速度。

浙公網安備 33010602011771號