開發案例——執行緒池/任務未抓取異常處理
阿新 • • 發佈:2019-02-11
問題描述:
- 使用 java.util.TimerTask 任務中斷(遇到未抓取異常時後續任務不執行);
2. 使用 java.util.concurrent.Executors.xxx 執行緒池對於未抓取異常無異常輸出,無法定位問題;
定位方法:
對比 TimerTask/Executors/Quartz 三者對丟擲異常的反應
TimerTask |
Executors |
Quartz |
|
是否中斷後續任務 |
是 |
否 |
否 |
是否有異常輸出 |
是(uncaught) |
無 |
是(log4j) |
問題解決:
建議:
- 對於定時任務,建議使用 quartz 庫。(使用 TimerTask 有未抓取異常時會導致當前Timer終止,後續任務無法執行)
- 執行緒池有未抓取異常時不會導致後續任務中斷,但是沒有異常資訊的輸出,難以定位問題,對此,有三種方案:
- )自己封裝一個RunnableWrapper、CallableWrapper,將傳入的任務包裹其中,在run方法中try-catch,並統一對未抓取異常進行異常處理/輸出;
- )繼承ThreadPoolExecutor的方式來建立執行緒池,重寫其afterExecute(Thread, Throwable)方法,判斷第二個引數非空時獲得其異常資訊,統一進行處理;(注意:僅對 executor.execute(..) 啟動的任務有效,executor.submit(..)的無效)
- )建立執行緒池時,傳入自定義的ThreadFactory,在其建立執行緒時,使用setUncaughtExceptionHandler(..)設定每個執行緒的未抓取異常處理控制代碼,統一進行處理;(注意:僅對 executor.execute(..) 啟動的任務有效,executor.submit(..)的無效)