1. 程式人生 > >執行緒八大基礎核心七(異常處理)

執行緒八大基礎核心七(異常處理)

1.引子

在java多執行緒併發程式設計中,有八大基礎核心。
看看都有哪八大基礎核心呢?它們分別是:
    1.建立執行緒的方式
    2.執行緒啟動
    3.執行緒停止
    4.執行緒生命週期
    5.執行緒相關的方法
    6.執行緒相關的屬性
    7.執行緒異常處理
    8.執行緒安全

今天我們從第七個基礎核心開始:執行緒異常處理

2.考考你

#前情回顧
在軟體專案開發中,除了要處理正常的業務流程外,異常處理也是我們繞不過去的一個坎

#考考你
1.你知道java的異常體系嗎?
2.你知道哪一種異常處理方式比較好嗎?
3.你知道如何使用UncaughtExceptionHandler嗎?

3.案例

3.1.難以發現的子執行緒異常

簡述:

1.在子執行緒child-exception-0中,丟擲異常

2.主執行緒main依然正常執行,在實際專案中,會導致難以發現子執行緒的異常情況

package com.anan.thread.threadexception;

/**
 * 主執行緒main不能發現子執行緒異常
 */
public class NotFoundChildThreadException {

    public static void main(String[] args) {
        // 建立執行緒物件
        Runnable r1 = new MyRunnable();
        Thread t1 = new Thread(r1,"child-exception-0");
        t1.start();

        // 主執行緒迴圈列印輸出,忽略子執行緒異常
        for (int i = 0; i < 5; i++) {
            System.out.println("主執行緒main輸出:風景這邊獨好!當前索引【"
                    + i + "】");
        }

    }

}

/**
 * 實現Runnable,建立執行緒
 */
class MyRunnable implements Runnable{
    public void run() {
        System.out.println(Thread.currentThread().getName() +
                "準備丟擲異常了...start");
        // 丟擲異常
        throw  new RuntimeException("子執行緒丟擲了異常.");
    }
}

執行結果:

 

 

 

3.2.不能捕獲的子執行緒異常

簡述:

1.建立3個子執行緒:thread-0、thread-1,thread-2

2.每個子執行緒都會丟擲異常

3.在主執行緒main中,進行捕獲處理。期望如果thread-0丟擲了異常,那麼thread-1/thread-2執行緒,不要建立執行

/**
 * 不能捕獲的子執行緒異常
 */
public class NotCaughtChildException {

    public static void main(String[] args) {
        // 預期子執行緒會丟擲異常,通過try{}catch(){}捕獲處理
        try{
            // 建立子執行緒0
            Runnable r1 = new MyRunnable1();
            Thread t0 = new Thread(r1,"thread-0");
            t0.start();

            // 建立子執行緒1
            Thread t1 = new Thread(r1,"thread-1");
            t1.start();

            // 建立子執行緒2
            Thread t2 = new Thread(r1,"thread-2");
            t2.start();

        }catch (RuntimeException e){
            System.out.println("捕獲到了異常.");
        }
    }
}

/**
 * 實現Runnable,建立執行緒
 */
class MyRunnable1 implements Runnable{
    public void run() {
        System.out.println(Thread.currentThread().getName() +
                "準備丟擲異常了...start");
        // 丟擲異常
        throw  new RuntimeException("子執行緒丟擲了異常.");
    }
}

執行結果:

 

 

 

3.3.全域性異常處理

簡述:

1.在3.2.中,不能通過try{}catch(){}捕獲子執行緒異常。因為try{}catch(){}只能捕獲當前執行緒的異常

2.如果要對所有子執行緒,進行統一異常處理,需要一個全域性異常處理器

3.全域性異常處理器介面:Thread.UncaughtExceptionHandler

4.實現方式:

4.1.編寫全域性異常處理器,實現介面:Thread.UncaughtExceptionHandler
4.2.註冊使用全域性異常處理器

3.3.1.全域性異常處理器

package com.anan.thread.threadexception;

/**
 * 自定義全域性異常處理器類
 */
public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

    public void uncaughtException(Thread t, Throwable e) {
        System.out.println(t.getName() + "發生了異常,異常訊息:" + e.getMessage());
    }
}

3.3.2.註冊使用全域性異常處理器

package com.anan.thread.threadexception;

/**
 * 註冊使用自定義全域性異常處理器
 */
public class UseUncaughtExceptionHandler {

    public static void main(String[] args) {

        // 關鍵程式碼:設定全域性異常處理器
        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());

        // 建立子執行緒0
        Runnable r1 = new MyRunnable1();
        Thread t0 = new Thread(r1,"thread-0");
        t0.start();

        // 建立子執行緒1
        Thread t1 = new Thread(r1,"thread-1");
        t1.start();

        // 建立子執行緒2
        Thread t2 = new Thread(r1,"thread-2");
        t2.start();
    }
}

/**
 * 實現Runnable,建立執行緒
 */
class MyRunnable2 implements Runnable{
    public void run() {
        System.out.println(Thread.currentThread().getName() +
                "準備丟擲異常了...start");
        // 丟擲異常
        throw  new RuntimeException("子執行緒丟擲了異常.");
    }
}

3.3.3.執行結果

 

 

4.討論分享

#考考你答案
1.你知道java的異常體系嗎?
  1.1.java異常體系中,老祖宗是Throwable
  1.2.在Throwable下,有Exception異常體系(日常開發中,見得最多)
  1.3.在Throwable下,有Error錯誤體系(日常開發中,較少關注)
    
2.你知道哪一種異常處理方式比較好嗎?
  2.1.通過案例演示,我們知道不能通過try{}catch(){},跨執行緒捕獲異常。try{}catch(){}只能捕獲當前執行緒自己的異常
  
  2.2.處理方式一:
   2.2.1.可以在當前執行緒中進行try{}catch(){},捕獲處理當前執行緒的異常
   2.2.2.該種方式處理起來程式碼量多、繁瑣。不推薦使用
   
  2.3.處理方式二:
   2.3.1.通過設定全域性異常處理器:UncaughtExceptionHandler
   2.3.2.實現異常全域性統一處理。推薦使用
   
3.你知道如何使用UncaughtExceptionHandler嗎?
  3.1.編寫全域性異常處理器,實現介面:
   Thread.UncaughtExceptionHandler
  3.2.註冊使用全域性異常處理器:
   // 關鍵程式碼:設定全域性異常處理器
        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());

java異常體系類圖:

&n