close

點擊關注公眾號,實用技術文章及時了解


ThreadPoolExecutor.execute源碼分析

看源碼可以知道,ThreadPoolExecutor中的任務都是在runWorker中執行的

通過源碼可以看到

1149行執行用戶任務
1150~1155處理捕獲任務異常,並拋出
拋出異常後會退出,從任務隊列中拉取任務的循環
然後執行1167行,worker線程退出的邏輯

看一下線程退出的邏輯

如果是異常退出,參數completedAbruptly為true
如果狀態值比STOP小,即線程池沒有停止,會重新創建一個worker線程
總結

ThreadPoolExecutor.execute 如果用戶任務拋出了異常,在線程池運行的狀態下,會重新創建一個worker線程。

這裡就可能存在一個風險,即如果用戶任務大量的拋出異常,可能會導出線程資源頻繁的銷毀、創建。

因此,需要用戶任務應當主動對異常進行處理,而不是消極的拋給線程池。

ThreadPoolExecutor.submit源碼分析

通過 ThreadPoolExecutor.submit 提交的用戶任務,會包裝成一個FutureTask,返回一個Future對象。因此異常處理的邏輯和ThreadPoolExecutor.execute有些差別

看一個FutureTask.run方法

從源碼可以看到,FutureTask執行用戶任務,如果異常,不會對外拋出,僅是記錄

但是在調用Future.get時,會拋出異常,但此時的線程不是線程池的線程了,而是用戶線程,因此對線程池是友好的。

總結

ThreadPoolExecutor.submit 提交的用戶任務,會包裝成一個FutureTask,FutureTask執行用戶任務,如果異常,不會對外拋出,僅是記錄,但是在調用Future.get時,會拋出異常。

異常是在用戶線程中拋出的,因此不影響線程池中的線程。

ScheduledThreadPoolExecutor.schedule源碼分析

ScheduledThreadPoolExecutor.schedule會將用戶任務包裝為ScheduledFutureTask,ScheduledFutureTask是FutureTask的子類,看下ScheduledFutureTask的執行邏輯

ScheduledFutureTask是FutureTask的子類,所以有異常時,也不是拋出,而是記錄

293行對於非周期性任務,執行一次,如果有異常,不拋出,僅記錄
294~296對於周期性任務,執行完本次後,會設置下次執行的時間。如果本次出現異常,ScheduledFutureTask.super.runAndReset()返回結果為false(這個可以從源碼看到),此時不會設置下次任務調度的時間了,因此會導致周期性任務失效的現象,並且異常信息不會拋出,也不會打印
總結

ScheduledThreadPoolExecutor.schedule提交的用戶任務,如果出現異常,是不會拋出的,也不會打印。

對於非周期性任務和周期性任務,執行異常,都沒有辦法感知(不拋出、看不到)。

對於周期性任務,任何一次調度時,任務出現異常,都會導致後續無法調度。

因此,在使用這個線程池時,我們應當保證用戶任務不會拋出異常到執行線程,避免任務調度失效,和異常排查困難等問題。

思考:ThreadPoolExecutor.execute發生異常時為什麼要退出

ThreadPoolExecutor.execute出現用戶任務異常時,為什麼要退出當前線程,再重新創建一個線程呢?

我思考了半天,覺得原因之一可能是:

ThreadPoolExecutor的可以指定線程工廠,如果我的線程工廠是這樣的

ThreadFactorythreadFactory=newThreadFactory(){@OverridepublicThreadnewThread(Runnabler){Threadthread=newThread(r);thread.setUncaughtExceptionHandler(newThread.UncaughtExceptionHandler(){@OverridepublicvoiduncaughtException(Threadt,Throwablee){//處理異常的邏輯}});returnthread;}};

即在ThreadFactory創建線程時,指定了對未捕獲的異常的處理器。

這種情況下,如果線程池不把發生異常的線程退出,可能會導致異常沒有走到用戶期望的邏輯上,因此需要將發生異常的線程退出,然後JVM調用UncaughtExceptionHandler。

來源:blog.csdn.net/qq_26824159/article/
details/126767372

推薦

Java面試題寶典

技術內卷群,一起來學習!!

PS:因為公眾號平台更改了推送規則,如果不想錯過內容,記得讀完點一下「在看」,加個「星標」,這樣每次新文章推送才會第一時間出現在你的訂閱列表里。點「在看」支持我們吧!

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()