版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第Java如何主動從當前線程獲取異常信息目錄Java主動從當前線程獲取異常信息使用場景寫法Java捕獲并處理線程異常:Thread及ThreadPoolExecutor線程池異常捕獲通過Thread.UncaughtExceptionHandler捕獲線程異常ThreadPoolExecutor線程池異常捕獲
Java主動從當前線程獲取異常信息
使用場景
在單個方法內(nèi)主動捕獲異常,并將異常的錯誤棧信息以日志的方式打出來
寫法
當前方法throw了異常,即改方法存在異常的情況,則可以使用如下方式獲取當前線程中的異常:
//主動獲取當前線程異常棧信息
StackTraceElement[]stackTraceElements=Thread.currentThread().getStackTrace();
//以日志的方式打出
\n
每一行錯誤棧信息結(jié)束后換行
log.error(StringUtils.join(stackTraceElements,'\n'));
Java捕獲并處理線程異常:Thread及ThreadPoolExecutor線程池異常捕獲
通過Thread.UncaughtExceptionHandler捕獲線程異常
Thread.UncaughtExceptionHandler類的作用:捕獲并處理線程run方法拋出的異常。
使用示例
為單個線程設(shè)置異常捕獲
Thread.UncaughtExceptionHandlerexceptionHandler=(t,e)-{
System.out.println("報錯線程:"+t.getName());
System.out.println("線程拋出的異常:"+e);
Threadthread=newThread(()-{
thrownewRuntimeException("throwanewException!");
thread.setUncaughtExceptionHandler(exceptionHandler);//設(shè)置異常處理器
thread.start();
如果項目中,全局的Thread線程處理異常的方式都相同,那么可以設(shè)置一個全局的異常捕獲類。
Thread.UncaughtExceptionHandlerexceptionHandler=(t,e)-{
System.out.println("報錯線程:"+t.getName());
System.out.println("線程拋出的異常:"+e);
Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);
通過這種方式,后續(xù)的Thread都可以公用這個異常處理類。如果需要用其它方式處理異常時,只需要實現(xiàn)1中的內(nèi)容即可。
部分源碼解析
UncaughtExceptionHandler源碼
//Thread.UncaughtExceptionHandler
@FunctionalInterface
publicinterfaceUncaughtExceptionHandler{
voiduncaughtException(Threadt,Throwablee);
}
Thread中的UncaughtExceptionHandler屬性
//作用于當個Thread線程
privatevolatileUncaughtExceptionHandleruncaughtExceptionHandler;
//static修飾,其可以作用于所有Thread線程
privatestaticvolatileUncaughtExceptionHandlerdefaultUncaughtExceptionHandler;
在Thread中,會首先提供Thread私有的異常處理類,然后才是全局
publicUncaughtExceptionHandlergetUncaughtExceptionHandler(){
returnuncaughtExceptionHandler!=null
uncaughtExceptionHandler:group;
}
實現(xiàn)原理
當線程由于未捕獲的異常而即將終止時,Java虛擬機將使用調(diào)用線程的getUncaughtExceptionHandler方法,以此來獲取UncaughtExceptionHandler類,并執(zhí)行其對異常的處理方法。
如果一個線程沒有顯式實現(xiàn)UncaughtExceptionHandler,那么它的ThreadGroup對象將充當它的UncaughtExceptionHandler類。
//Thread#getUncaughtExceptionHandler
publicUncaughtExceptionHandlergetUncaughtExceptionHandler(){
returnuncaughtExceptionHandler!=null
uncaughtExceptionHandler:group;
}
ThreadGroup實現(xiàn)了UncaughtExceptionHandler類。
publicclassThreadGroupimplementsThread.UncaughtExceptionHandler{
//……
publicvoiduncaughtException(Threadt,Throwablee){
//父級ThreadGroup的處理方法
if(parent!=null){
parent.uncaughtException(t,e);
}else{
//Thread的全局默認處理方法
Thread.UncaughtExceptionHandlerueh=
Thread.getDefaultUncaughtExceptionHandler();
if(ueh!=null){
ueh.uncaughtException(t,e);
}elseif(!(einstanceofThreadDeath)){
System.err.print("Exceptioninthread\""
+t.getName()+"\"");
e.printStackTrace(System.err);
}
}
}
//……
}
ThreadPoolExecutor線程池異常捕獲
使用示例
要捕獲ThreadPoolExecutor線程池中的線程執(zhí)行異常,需要實現(xiàn)被protected修飾的方法afterExecute,在該方法里面處理異常即可。
//ThreadPoolExecutor#afterExecute
classExtendedExecutorextendsThreadPoolExecutor{
protectedvoidafterExecute(Runnabler,Throwablet){
super.afterExecute(r,t);
//如果Runnable是Future類型,那么異常將會直接通過Future返回
if(t==nullrinstanceofFuture){
try{
Objectresult=((Future)r).get();
}catch(CancellationExceptionce){
t=ce;
}catch(ExecutionExceptionee){
t=ee.getCause();
}catch(InterruptedExceptionie){
Thread.currentThread().interrupt();//ignore/reset
}
}
//非Future類型
if(t!=null)
System.out.println(t);
}
注意:實現(xiàn)afterExecute方法時,要正確嵌套多個覆蓋,子類通常應(yīng)在此方法的開頭調(diào)用super.afterExecute,以確保不會破壞其他父類方法的實現(xiàn)。
源碼解析
在ThreadPoolExecutor中,線程任務(wù)的實際執(zhí)行方法是runWorker,如下所示:
//ThreadPoolExecutor#runWorker
finalvoidrunWorker(Workerw){
Threadwt=Thread.currentThread();
Runnabletask=w.firstTask;//實際提交的任務(wù)
//…………
try{
beforeExecute(wt,task);//task執(zhí)行前的操作
Throwablethrown=null;//異常信息保存
try{
task.run();//執(zhí)行任務(wù)
}catch(RuntimeExceptionx){
thrown=x;throwx;
}catch(Errorx){
thrown=x;throwx;
}catch(Throwablex){
thrown=x;thrownewError(x);
}finally{
afterExecute(task,thrown);//task執(zhí)行后的操作,也就包括了異常的捕獲工作
}
}finally{
task=null;
pletedTasks++;
w.unlock();
}
//……
}
afterExecute方法在ThreadPoolExecutor,并沒有進行任何操作,就是對異常的線程靜默處理
//ThreadPoolExecutor#afterExecute
protectedvoidafterExecute(Runnabler,Throwablet){}
Callable類型的任務(wù),在執(zhí)行時會自己捕獲并維護執(zhí)行中的異常。
//AbstractExecutorService#submit
publicTFutureTsubmit(CallableTtask){
if(task==null)thrownewNullPointerException();
RunnableFutureTftask=newTaskFor(task);
execute(ftask);
returnftask;
//Callable任務(wù)會被封裝成FutureTask
protectedTRunnableFutureTnewTaskFor(CallableTcallable){
returnnewFutureTaskT(callable);
}
在FutureTask的run方法中,他們內(nèi)部會將整個任務(wù)用try-catch給包起來。因此,也不會拋出Callable#run執(zhí)行的內(nèi)部異常。
//FutureTask#run
publicvoidrun(){
//……
try{
CallableVc=callable;
//……
//這里將Callable的執(zhí)行過程產(chǎn)生的異常都捕獲了
try{
result
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 游泳培訓中心規(guī)章制度
- 煤礦承包商安全培訓制度
- 培訓機構(gòu)值班責任制度
- 內(nèi)部員工日常培訓制度
- 煤礦三級教育培訓管理制度
- 羅城鄉(xiāng)計生培訓制度
- 煤礦內(nèi)部培訓管理制度
- 兒童培訓門店管理制度
- 新崗位培訓制度及流程
- 英語培訓內(nèi)部管理制度
- 初中語文新課程標準與解讀課件
- 無人機裝調(diào)檢修工培訓計劃及大綱
- 中建通風與空調(diào)施工方案
- 高考語言運用題型之長短句變換 學案(含答案)
- 春よ、來い(春天來了)高木綾子演奏長笛曲譜鋼琴伴奏
- ARJ21機型理論知識考試題庫(匯總版)
- 2023年婁底市建設(shè)系統(tǒng)事業(yè)單位招聘考試筆試模擬試題及答案解析
- GB/T 4623-2014環(huán)形混凝土電桿
- GB/T 32065.4-2015海洋儀器環(huán)境試驗方法第4部分:高溫試驗
- GB/T 16823.3-2010緊固件扭矩-夾緊力試驗
- 中介服務(wù)費承諾書
評論
0/150
提交評論