執行緒管理(八)線上程裡處理不受控制的異常
宣告:本文是《 Java 7 Concurrency Cookbook 》的第一章, 作者: Javier Fernández González 譯者:鄭玉婷 校對:方騰飛
線上程裡處理不受控制的異常
Java裡有2種異常:
- 檢查異常(Checked exceptions): 這些異常必須強制捕獲它們或在一個方法裡的throws子句中。 例如, IOException 或者ClassNotFoundException。
- 未檢查異常(Unchecked exceptions): 這些異常不用強制捕獲它們。例如, NumberFormatException。
在一個執行緒 物件的 run() 方法裡丟擲一個檢查異常,我們必須捕獲並處理他們。因為 run() 方法不接受 throws 子句。當一個非檢查異常被丟擲,預設的行為是在控制檯寫下stack trace並退出程式。
幸運的是, Java 提供我們一種機制可以捕獲和處理執行緒物件丟擲的未檢測異常來避免程式終結。
在這個指南中, 我們將用例項來學習這個機制。
準備
指南中的例子是使用Eclipse IDE 來實現的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 開啟並建立一個新的java專案。
怎麼做呢…
按照這些步驟來實現下面的例子:
1. 首先, 我們必須實現一個類來處理非檢查異常。這個類必須實現 UncaughtExceptionHandler 介面並實現在介面內已宣告的uncaughtException() 方法。在這裡,命名此類為 ExceptionHandler ,並讓此方法裡寫有關於丟擲異常的執行緒資訊和異常資訊,按照下面的程式碼:
public class ExceptionHandler implements UncaughtExceptionHandler { public void uncaughtException(Thread t, Throwable e) { System.out.printf("An exception has been captured\n"); System.out.printf("Thread: %s\n",t.getId()); System.out.printf("Exception: %s: %s\n",e.getClass().getName(),e.getMessage()); System.out.printf("Stack Trace: \n"); e.printStackTrace(System.out); System.out.printf("Thread status: %s\n",t.getState()); } }
2. 現在,實現一個類丟擲非檢查異常。 命名此類為Task一定要實現 Runnable 介面,實現 run() 方法並刻意出異常, 例如,嘗試將 string 值轉化成 int 值。
public class Task implements Runnable { @Override public void run() { int numero=Integer.parseInt("TTT"); } }
3. 現在,實現例子主類。實現 Main類和 main() 方法.
public class Main { public static void main(String[] args) {
4. 建立 Task 物件並用執行緒執行它。使用 setUncaughtExceptionHandler() 方法設定非檢查異常 handler 並開始執行執行緒。
Task task=new Task(); Thread thread=new Thread(task); thread.setUncaughtExceptionHandler(new ExceptionHandler()); thread.start(); } }
5. 執行例子並檢視結果。
它是怎麼工作的…
在下面的裁圖,你可以發現例子的執行結果。異常被handler捕捉,並在操控臺寫下了有關異常和丟擲它的執行緒的資訊。請看下圖:
當在一個執行緒裡丟擲一個異常,但是這個異常沒有被捕獲(這肯定是非檢查異常), JVM 檢查執行緒的相關方法是否有設定一個未捕捉異常的處理者 。如果有,JVM 使用Thread 物件和 Exception 作為引數呼叫此方法 。
如果執行緒沒有捕捉未捕獲異常的處理者, 那麼 JVM會把異常的 stack trace 寫入操控臺並結束任務。
更多…
The Thread 類有其他相關方法可以處理未捕獲的異常。靜態方法 setDefaultUncaughtExceptionHandler() 為應用裡的所有執行緒物件建立異常 handler 。
當一個未捕捉的異常線上程裡被丟擲,JVM會尋找此異常的3種可能潛在的處理者(handler)。
首先, 它尋找這個未捕捉的執行緒物件的異常handle,如我們在在這個指南中學習的。如果這個handle 不存在,那麼JVM會線上程物件的ThreadGroup裡尋找非捕捉異常的handler,如在處理執行緒組內的不受控制異常裡介紹的那樣。如果此方法不存在,正如我們在這個指南中學習的,那麼 JVM 會尋找預設非捕捉異常handle。
如果沒有一個handler存在, 那麼 JVM會把異常的 stack trace 寫入操控臺並結束任務。
參見
- 第一章:執行緒管理:在執行緒組裡處理不受控制的異常