Java サブスレッドでの例外処理の一般的な方法の概要

黄舟
リリース: 2017-09-26 09:27:24
オリジナル
1609 人が閲覧しました

以下のエディターは、Java サブスレッドでの例外処理メソッド (一般) に基づいた記事を提供します。編集者はこれがとても良いものだと思ったので、皆さんの参考として今から共有します。エディターを追って見てみましょう。通常のシングルスレッド プログラムでは、例外をキャッチするには try...catch...finally... コード ブロックのみが必要です。では、同時実行の状況では、たとえば、子スレッドが親スレッドで開始された場合、親スレッドで子スレッドからの例外をキャッチし、それに応じて処理するにはどうすればよいでしょうか?

よくある間違い とても簡単なことだと思う人もいるかもしれませんが、親スレッドが子スレッドを開始する場所を直接キャッチしてください。実際、これは間違っています。

原因分析 Runnable インターフェイスの run メソッドの完全なシグネチャを思い出してください。 throws ステートメントが識別されていないため、メソッドはチェック例外をスローしません。 RuntimeException などの未チェック例外については、JVM によって新規スレッドがスケジュールされて実行されるため、例外が発生しても親スレッドには通知されません。

public abstract void run()

Solutionそれでは、親スレッドで子スレッドからの例外をキャッチするにはどうすればよいでしょうか?筆者はよくある方法を3つ考え、みんなに共有しました。

方法 1: 子スレッドで 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();
 }
}
ログイン後にコピー

方法 2: スレッドの例外ハンドラー UncaughtExceptionHandler を設定しますスレッドの例外ハンドラーを設定します。具体的なメソッドは次のとおりです。

(1) Thread.setUncaughtExceptionHandler は、現在のスレッドの例外ハンドラーを設定します。

(2) Thread.setDefaultUncaughtExceptionHandler は、現在のスレッドに例外ハンドラーがある場合、プログラム全体のデフォルトの例外ハンドラーを設定します。 (デフォルトは none) )、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));
  }
 }
}
ログイン後にコピー

コマンドライン出力: 子スレッドで 1

例外を処理します。 lang .RuntimeException: ChildThread例外

方法3、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();
   }
  }
 }
}
ログイン後にコピー

コマンドライン出力: 子スレッドで1

例外を処理します。java.util.concurrent.ExecutionException: java.lang.RuntimeException。 : ChildThread1 例外

概要上記は、よく使用される 3 つの Java 子スレッド例外処理メソッドです。実際、著者は特定のシナリオで他のいくつかの解決策も考えました。それらについてはまた別の機会に分析しますので、よろしくお願いします~

以上がJava サブスレッドでの例外処理の一般的な方法の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート