最近有個同學(xué)問我這樣一段代碼,代碼如下:
第一段代碼是這樣的,try catch是將整個線程都放在try代碼塊中。

第二塊代碼是將線程里面的run方法代碼塊進(jìn)行try catch。

大家可能第一反應(yīng)都是覺得只是try的代碼塊不一樣,范圍不一樣了而已。但是可曾想過就是這個try的地方不一樣導(dǎo)致了不同的結(jié)果。第一種try方式當(dāng)里面的run()方法執(zhí)行時報了異常是捕獲不到的,整個程序會crash掉;而第二種 try方式程序是不會crash掉。開始我一直在想,兩個try catch方式真的只有范圍不同而已,而且第一種范圍更廣一些,為什么捕獲不到異常呢?
其實從一開始思考就是有出了問題,為什么這么說?有沒有發(fā)現(xiàn)這種兩try 本質(zhì)區(qū)別在哪里?根本原因是在于這兩種try是在不同線程,第一種是在ui線程進(jìn)行的,第二種是在另啟的線程中。所以這才是導(dǎo)致出現(xiàn)上述問題的根本。我在網(wǎng)上找了一些官話來解釋原因是這樣說的:多線程運(yùn)行不能按照順序執(zhí)行過程中捕獲異常的方式來處理異常,異常會被直接拋出到控制臺(由于線程的本質(zhì),使得你不能捕獲從線程中逃逸的異常。一旦異常逃逸出任務(wù)的run方法,它就會向外傳播到控制臺,除非你采用特殊的形式捕獲這種異常)。可以這么說try的時機(jī)與拋出異常的線程不一致,所以導(dǎo)致異常逃逸,從而捕獲不到,導(dǎo)致程序crash。
下面再給大家貼下多線程中如何去捕獲異常:
/* * 第一步:定義符合線程異常處理器規(guī)范的“異常處理器” * 實現(xiàn)Thread.UncaughtExceptionHandler規(guī)范 */class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{ /* * Thread.UncaughtExceptionHandler.uncaughtException()會在線程因未捕獲的異常而臨近死亡時被調(diào)用 */ @Override public void uncaughtException(Thread t, Throwable e) { System.out.PRintln("caught "+e); }}2.定義使用該異常處理器的線程工廠
/* * 第二步:定義線程工廠 * 線程工廠用來將任務(wù)附著給線程,并給該線程綁定一個異常處理器 */class HanlderThreadFactory implements ThreadFactory{ @Override public 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{ @Override public void run() { Thread t = Thread.currentThread(); System.out.println("run() by "+t); System.out.println("eh = "+t.getUncaughtExceptionHandler()); throw new RuntimeException(); }}4.調(diào)用實驗
/* * 第四步:使用線程工廠創(chuàng)建線程池,并調(diào)用其execute方法 */public class ThreadExceptionUncaughtExceptionHandler{ public static void main(String[] args){ ExecutorService exec = Executors.newCachedThreadPool(new HanlderThreadFactory()); exec.execute(new ExceptionThread()); }}![]()
注:以上代碼均來自《thinking in java》,如有錯誤,歡迎批評指正
新聞熱點(diǎn)
疑難解答
圖片精選