Java如何主動從當前線程獲取異常信息_第1頁
Java如何主動從當前線程獲取異常信息_第2頁
Java如何主動從當前線程獲取異常信息_第3頁
Java如何主動從當前線程獲取異常信息_第4頁
Java如何主動從當前線程獲取異常信息_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論