1. 程式人生 > >處理執行緒非受控異常

處理執行緒非受控異常

處理執行緒非受控異常


能夠幫助管理應用中的錯誤情況,這是任何程式語言都應具備的重要機制。如同大多數現代程式語言一樣,Java語言實現了基於異常的機制來管理錯誤情況。當檢測出錯誤的時候,Java類會丟擲這些異常。也可以使用這些異常或者實現定製化異常來管理程式造成的錯誤。

Java還提供一種捕獲和處理這些異常的機制。方法中必須被捕獲或者使用throws語句再次丟擲的異常是受檢異常,無須指定或捕獲的異常稱為非受檢異常。

  • 受檢異常 : 必須在方法的throws語句中指定或內部捕獲的異常,例如,IOException 或者 ClassNotFoundException。
  • 非受檢異常 : 無須指定或捕獲的異常,例如NumberFormatException。

當受檢異常線上程物件的run()方法中被丟擲來時,由於run()方法不接受throws語句,所以必須捕獲和處理這些異常。當非受檢異常線上程物件的run()方法中被丟擲來時,預設行為是在控制檯輸出堆疊跟蹤,同時退出程式。

不過Java提供了一種機制來捕獲和處理執行緒物件丟擲的非受控異常,避免終止程式。

在本節中,通過範例學習這種機制原理。

準備工作

本範例通過Eclipse開發工具實現。如果使用諸如NetBeans的開發工具,開啟並建立一個新的Java專案。

實現過程

通過如下步驟完成範例:

  1. 首先,實現一個類來處理非受檢異常。這個類必須實現UncaughtExceptionHandler介面和介面定義的uncaughtException()方法,此方法依附Thread類。在本範例中,此類命名為ExceptionHandler,然後實現方法記錄丟擲的Exception和Thread資訊。程式碼如下:

    public class ExceptionHandler implements UncaughtExceptionHandler {
    	@Override
    	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()方法。強制其報錯,例如,嘗試將字串轉換成整型:

    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()設定非受控異常處理器,開始執行執行緒:

    		Task task = new Task();
    		Thread thread = new Thread(task);
    		thread.setUncaughtExceptionHandler(new ExceptionHandler());
    		thread.start();
    	}
    }
    
  5. 執行程式,檢視結果。

工作原理

在下圖中顯示執行範例輸出的結果。通過控制器丟擲和捕獲的異常記錄丟擲的Exception和Thread資訊,然後輸出到控制檯上:

pics/01_05.jpg

當執行緒中被丟擲一個異常並且始終未捕獲(非受檢異常),Java虛擬機器檢查執行緒是否有通過匹配方法設定的非捕獲異常控制器。如果有,Java虛擬機器用Thread物件和Exception引數呼叫此方法。

如果執行緒沒有非捕獲異常處理器,Java虛擬機器會在控制檯輸出堆疊跟蹤,並且終止執行已經丟擲異常的執行緒。

擴充套件學習

Thread類中的靜態方法setDefaultUncaughtExcptionHandler()也與非捕獲異常處理有關,此方法為應用中的所有執行緒物件建立一個異常處理器。

當執行緒中丟擲一個非捕獲異常時,Java虛擬機器尋找異常中三個可能的處理器。

首先是尋找執行緒物件的非捕獲異常處理器,也就是本節中學到的。如果此處理器不存在,Java虛擬機器尋找ThreadGroup類中的非捕獲異常控制器,這個類在“執行緒組中分組執行緒、處理非受控異常”小節中學習。如果此方法也不存在,Java虛擬機器會尋找預設的非捕獲異常處理器。

如果三種處理器均不存在,Java虛擬器在控制檯輸出異常的堆疊跟蹤,並且終止執行已經丟擲異常的執行緒。

更多關注

  • 本章中“工廠模式建立執行緒”小節。