首頁 > Java > java教程 > Java子執行緒中的異常處理的通用方法介紹

Java子執行緒中的異常處理的通用方法介紹

黄舟
發布: 2017-09-26 09:27:24
原創
1657 人瀏覽過

下面小編就為大家帶來一篇基於Java子執行緒中的異常處理方法(通用)。小編覺得蠻不錯的,現在就分享給大家,也給大家做個參考。一起跟著小編過來看看吧

在普通的單線程程式中,捕獲異常只需要通過try ... catch ... finally ...代碼塊就可以了。那麼,在並發情況下,例如在父線程中啟動了子線程,如何在父線程中捕獲來自子線程的異常,從而進行相應的處理呢?

常見錯誤

也許有人會覺得,很簡單嘛,直接在父執行緒啟動子執行緒的地方try ... catch一把就可以了,其實這是不對的。

原因分析

讓我們回想一下Runnable介面的run方法的完整簽名,因為沒有標識throws語句,所以方法是不會拋出checked異常的。至於RuntimeException這樣的unchecked異常,由於新執行緒由JVM進行調度執行,如果發生了異常,也不會通知到父執行緒。

public abstract void run()

解決方案

那麼,如何在父執行緒中擷取來自子執行緒的異常呢?樓主想到了3種常用方法,分享給大家。

方法一:子執行緒中try... catch...

#最簡單有效的辦法,就是在子執行緒的方法中,把可能發生異常的地方,用try ... catch ... 語句包起來。子執行緒程式碼:


public class ChildThread implements Runnable {
 public void run() {
  doSomething1();
  try {
   // 可能发生异常的方法
   exceptionMethod();
  } catch (Exception e) {
   // 处理异常
   System.out.println(String.format("handle exception in child thread. %s", e));
  }
  doSomething2();
 }
}
登入後複製

方法二:設定異常處理器UncaughtExceptionHandler


#為執行緒設定異常處理器。具體做法可以是以下幾種:


(1)Thread.setUncaughtExceptionHandler設定目前執行緒的例外處理器

(2)Thread.setDefaultUncaughtExceptionHandler為整個程式設定預設的例外處理器如果目前執行緒有異常處理器(預設沒有),則優先使用該UncaughtExceptionHandler類別;否則,如果當前執行緒所屬的執行緒組有異常處理器,則使用執行緒組的ExceptionHandler;否則,使用全域預設的DefaultUncaughtExceptionHandler;如果都沒有的話,子執行緒就會退出。

注意:子執行緒中發生了異常,如果沒有任何類別來接手處理的話,是會直接退出的,而不會留下列印任何日誌。所以,如果什麼都不做的話,是會出現子執行緒任務既沒執行,也沒有任何日誌提示的「詭異」現象的。

設定目前執行緒的例外處理器:

public class ChildThread implements Runnable { 
 private static ChildThreadExceptionHandler exceptionHandler;

 static {
  exceptionHandler = new ChildThreadExceptionHandler();
 }

 public void run() {
  Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler);
  System.out.println("do something 1");
  exceptionMethod();
  System.out.println("do something 2");
 }

 public static class ChildThreadExceptionHandler implements Thread.UncaughtExceptionHandler {
  public void uncaughtException(Thread t, Throwable e) {
   System.out.println(String.format("handle exception in child thread. %s", e));
  }
 }
}
登入後複製

或者,設定所有執行緒的預設例外處理器

public class ChildThread implements Runnable {
 private static ChildThreadExceptionHandler exceptionHandler;

 static {
  exceptionHandler = new ChildThreadExceptionHandler();
  Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);
 }

 public void run() {
  System.out.println("do something 1");
  exceptionMethod();
  System.out.println("do something 2");
 }

 private void exceptionMethod() {
  throw new RuntimeException("ChildThread exception");
 }

 public static class ChildThreadExceptionHandler implements Thread.UncaughtExceptionHandler {
  public void uncaughtException(Thread t, Throwable e) {
   System.out.println(String.format("handle exception in child thread. %s", e));
  }
 }
}
登入後複製

命令列輸出:do something 1

handle exception in child thread. java.lang.RuntimeException: ChildThread exception


方法三,透過Future的get方法捕獲異常

使用線程池提交一個能獲取到返回資訊的方法,也就是ExecutorService.submit(Callable)在submit之後可以獲得一個線程執行結果的Future對象,而如果子執行緒中發生了異常,透過future.get()取得回傳值時,可以擷取到ExecutionException異常,從而知道子執行緒中發生了異常。

子執行緒程式碼:

public class ChildThread implements Callable {
 public Object call() throws Exception {
  System.out.println("do something 1");
  exceptionMethod();
  System.out.println("do something 2");
  return null;
 }

 private void exceptionMethod() {
  throw new RuntimeException("ChildThread1 exception");
 }
}
登入後複製

父執行緒程式碼:

######
public class Main {
 public static void main(String[] args) {
  ExecutorService executorService = Executors.newFixedThreadPool(8);
  Future future = executorService.submit(new ChildThread());
  try {
   future.get();
  } catch (InterruptedException e) {
   System.out.println(String.format("handle exception in child thread. %s", e));
  } catch (ExecutionException e) {
   System.out.println(String.format("handle exception in child thread. %s", e));
  } finally {
   if (executorService != null) {
    executorService.shutdown();
   }
  }
 }
}
登入後複製
###命令列輸出: do something 1######handle exception in child thread. java.util.concurrent.ExecutionException: java.lang.RuntimeException: ChildThread1 exception############總結###### ######上面就是3種常用的Java子執行緒異常處理方法。其實樓主還想到了另外幾個特定場景下的解決方法,改天再分析,謝謝大家支持~###

以上是Java子執行緒中的異常處理的通用方法介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板