多线程的异常捕捉
為什么要單獨(dú)講多線程的異常捕捉呢?先看個例子:
public class ThreadException implements Runnable{@Overridepublic void run() {throw new RuntimeException();}//現(xiàn)象:控制臺打印出異常信息,并運(yùn)行一段時間后才停止public static void main(String[] args){//就算把線程的執(zhí)行語句放到try-catch塊中也無濟(jì)于事try{ExecutorService exec = Executors.newCachedThreadPool();exec.execute(new ThreadException());}catch(RuntimeException e){System.out.println("Exception has been handled!");}} }在run中手動拋出了一個運(yùn)行時異常,在main中啟動線程,catch語句塊中捕捉下異常,捕捉到打印一句話。運(yùn)行結(jié)果如下圖:
發(fā)現(xiàn)異常被拋到了控制臺,沒有打印catch塊中的語句。
結(jié)論:多線程運(yùn)行不能按照順序執(zhí)行過程中捕獲異常的方式來處理異常,異常會被直接拋出到控制臺(由于線程的本質(zhì),使得你不能捕獲從線程中逃逸的異常。一旦異常逃逸出任務(wù)的run方法,它就會向外傳播到控制臺,除非你采用特殊的形式捕獲這種異常。),這樣會讓你很頭疼,無法捕捉到異常就無法處理異常而引發(fā)的問題。
于是,我們一定會想如何在多線程中捕捉異常呢?
二、多線程中捕捉異常
我們來按照下面的步驟完成這次實(shí)驗(yàn):
1.定義異常處理器
要求,實(shí)現(xiàn)?Thread.UncaughtExceptionHandler的uncaughtException方法,如下:
/** 第一步:定義符合線程異常處理器規(guī)范的“異常處理器”* 實(shí)現(xiàn)Thread.UncaughtExceptionHandler規(guī)范*/ class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{/** Thread.UncaughtExceptionHandler.uncaughtException()會在線程因未捕獲的異常而臨近死亡時被調(diào)用*/@Overridepublic void uncaughtException(Thread t, Throwable e) {System.out.println("caught "+e);} }?
2.定義使用該異常處理器的線程工廠
/** 第二步:定義線程工廠* 線程工廠用來將任務(wù)附著給線程,并給該線程綁定一個異常處理器*/ class HanlderThreadFactory implements ThreadFactory{@Overridepublic Thread newThread(Runnable r) {System.out.println(this+"creating new Thread");Thread t = new Thread(r);System.out.println("created "+t);t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());//設(shè)定線程工廠的異常處理器System.out.println("eh="+t.getUncaughtExceptionHandler());return t;} }3.定義一個任務(wù),讓其拋出一個異常
/** 第三步:我們的任務(wù)可能會拋出異常* 顯示的拋出一個exception*/ class ExceptionThread implements Runnable{@Overridepublic void run() {Thread t = Thread.currentThread();System.out.println("run() by "+t);System.out.println("eh = "+t.getUncaughtExceptionHandler());throw new RuntimeException();} }4.調(diào)用實(shí)驗(yàn)
/** 第四步:使用線程工廠創(chuàng)建線程池,并調(diào)用其execute方法*/ public class ThreadExceptionUncaughtExceptionHandler{public static void main(String[] args){ExecutorService exec = Executors.newCachedThreadPool(new HanlderThreadFactory());exec.execute(new ExceptionThread());} }運(yùn)行結(jié)果如下圖:
三、結(jié)論
在java中要捕捉多線程產(chǎn)生的異常,需要自定義異常處理器,并設(shè)定到對應(yīng)的線程工廠中(即第一步和第二步)。
四、拓展
如果你知道將要在代碼中處處使用相同的異常處理器,那么更簡單的方式是在Thread類中設(shè)置一個靜態(tài)域,并將這個處理器設(shè)置為默認(rèn)的未捕獲處理器。
這個處理器只有在不存在線程專有的未捕獲異常處理器的情況下才會被調(diào)用。
public static void main(String[] args){Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());ExecutorService exec =Executors.newCachedThreadPool();exec.execute(new ExceptionThread()); }總結(jié)
- 上一篇: 深度学习CNN算法原理
- 下一篇: MAC 下MySQL常用命令