處理執行緒非受控異常
處理執行緒非受控異常
能夠幫助管理應用中的錯誤情況,這是任何程式語言都應具備的重要機制。如同大多數現代程式語言一樣,Java語言實現了基於異常的機制來管理錯誤情況。當檢測出錯誤的時候,Java類會丟擲這些異常。也可以使用這些異常或者實現定製化異常來管理程式造成的錯誤。
Java還提供一種捕獲和處理這些異常的機制。方法中必須被捕獲或者使用throws語句再次丟擲的異常是受檢異常,無須指定或捕獲的異常稱為非受檢異常。
- 受檢異常 : 必須在方法的throws語句中指定或內部捕獲的異常,例如,IOException 或者 ClassNotFoundException。
- 非受檢異常 : 無須指定或捕獲的異常,例如NumberFormatException。
當受檢異常線上程物件的run()方法中被丟擲來時,由於run()方法不接受throws語句,所以必須捕獲和處理這些異常。當非受檢異常線上程物件的run()方法中被丟擲來時,預設行為是在控制檯輸出堆疊跟蹤,同時退出程式。
不過Java提供了一種機制來捕獲和處理執行緒物件丟擲的非受控異常,避免終止程式。
在本節中,通過範例學習這種機制原理。
準備工作
本範例通過Eclipse開發工具實現。如果使用諸如NetBeans的開發工具,開啟並建立一個新的Java專案。
實現過程
通過如下步驟完成範例:
-
首先,實現一個類來處理非受檢異常。這個類必須實現UncaughtExceptionHandler介面和介面定義的uncaughtException()方法,此方法依附Thread類。在本範例中,此類命名為ExceptionHandler,然後實現方法記錄丟擲的Exception和Thread資訊。程式碼如下:
public class ExceptionHandler implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.
-
現在,實現一個類丟擲非受檢異常。此類命名為Task,指定其實現Runnable介面和run()方法。強制其報錯,例如,嘗試將字串轉換成整型:
public class Task implements Runnable { @Override public void run() { int numero = Integer.parseInt("TTT"); } }
-
現在實現主類,包含main()方法的Main類:
public class Main { public static void main(String[] args) {
-
建立Task物件,以及執行此物件的執行緒。使用setUncaughtExceptionHandler()設定非受控異常處理器,開始執行執行緒:
Task task = new Task(); Thread thread = new Thread(task); thread.setUncaughtExceptionHandler(new ExceptionHandler()); thread.start(); } }
-
執行程式,檢視結果。
工作原理
在下圖中顯示執行範例輸出的結果。通過控制器丟擲和捕獲的異常記錄丟擲的Exception和Thread資訊,然後輸出到控制檯上:
當執行緒中被丟擲一個異常並且始終未捕獲(非受檢異常),Java虛擬機器檢查執行緒是否有通過匹配方法設定的非捕獲異常控制器。如果有,Java虛擬機器用Thread物件和Exception引數呼叫此方法。
如果執行緒沒有非捕獲異常處理器,Java虛擬機器會在控制檯輸出堆疊跟蹤,並且終止執行已經丟擲異常的執行緒。
擴充套件學習
Thread類中的靜態方法setDefaultUncaughtExcptionHandler()也與非捕獲異常處理有關,此方法為應用中的所有執行緒物件建立一個異常處理器。
當執行緒中丟擲一個非捕獲異常時,Java虛擬機器尋找異常中三個可能的處理器。
首先是尋找執行緒物件的非捕獲異常處理器,也就是本節中學到的。如果此處理器不存在,Java虛擬機器尋找ThreadGroup類中的非捕獲異常控制器,這個類在“執行緒組中分組執行緒、處理非受控異常”小節中學習。如果此方法也不存在,Java虛擬機器會尋找預設的非捕獲異常處理器。
如果三種處理器均不存在,Java虛擬器在控制檯輸出異常的堆疊跟蹤,並且終止執行已經丟擲異常的執行緒。
更多關注
- 本章中“工廠模式建立執行緒”小節。