執行緒八大基礎核心七(異常處理)
阿新 • • 發佈:2020-02-16
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