質問

それを見つけた後 FutureTask で実行します Executors.newCachedThreadPool() Java 1.6(およびEclipseから)では、 Runnable.run() 方法、私はすべての人にスロー/キャッチを追加せずにこれらをキャッチする方法を考え出そうとしました Runnable 実装。

APIは、そのオーバーライドを示唆しています FutureTask.setException() これで支援する必要があります:

この未来は、この将来がすでに設定されているか、キャンセルされていない限り、その原因として与えられたスロー可能なexecutionExceptionを報告します。この方法は、計算の障害時に実行方法によって内部的に呼び出されます。

ただし、この方法は呼ばれていないようです(デバッガーで実行すると、例外がキャッチされていることが示されています FutureTask, 、 しかし setException 呼ばれていません)。私の問題を再現するために、次のプログラムを書きました:

public class RunTest {
    public static void main(String[] args) {
        MyFutureTask t = new MyFutureTask(new Runnable() {

            @Override
            public void run() {
                throw new RuntimeException("Unchecked exception");

            }
        });

        ExecutorService service = Executors.newCachedThreadPool();
        service.submit(t);
    }
}

public class MyFutureTask extends FutureTask<Object> {

    public MyFutureTask(Runnable r) {
        super(r, null);
    }

    @Override
    protected void setException(Throwable t) {
        super.setException(t);
        System.out.println("Exception: " + t);
    }
}

私の主な質問は、FutureTaskでスローされた例外をキャッチするにはどうすればよいですか?なぜそうしないのですか setException 呼ばれますか?

また、理由を知りたいです Thread.UncaughtExceptionHandler メカニズムは使用されていません FutureTask, 、これに理由はありますか?

役に立ちましたか?

解決

setException おそらくオーバーライドのために作られたものではありませんが、ニーズが生じた場合に結果を例外に設定できるように提供されます。あなたがしたいのは、オーバーライドすることです done() 方法と結果を取得してみてください:

public class MyFutureTask extends FutureTask<Object> {

    public MyFutureTask(Runnable r) {
        super(r, null);
    }

    @Override
    protected void done() {
        try {
            if (!isCancelled()) get();
        } catch (ExecutionException e) {
            // Exception occurred, deal with it
            System.out.println("Exception: " + e.getCause());
        } catch (InterruptedException e) {
            // Shouldn't happen, we're invoked when computation is finished
            throw new AssertionError(e);
        }
    }
}

他のヒント

を使用してみましたか UncaughtExceptionHandler?

  • 実装する必要があります UncaughtExceptionHandler インターフェース。
  • 設定する UncaughtExceptionHandler プールスレッドの場合は、aを提供します ThreadFactory の中に Executor.newCachedThreadPool(ThreadFactory) 電話。
  • 作成されたスレッドのUncaughexceptionHandlerを介して設定できます setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

でタスクを送信します ExecutorService.execute, 、提出されたタスクからスローされた例外のみが execute 無作法な例外ハンドラーに到達します。提出されたタスクの場合 ExecutorService.submit スローされた例外は、タスクの返品値の一部であると見なされます。送信で提出されたタスクが例外を除いて終了した場合、呼び出すときにそれはret延します Future.get, 、に包まれています ExecutionException

はるかに優れた解決策:Java FutureTask完了チェック

あなたが電話するとき futureTask.get() 計算の結果を取得するために、基礎となる場合、例外(executionException)がスローされます Runnable/Callable 例外を投げました。

ExecutionException.getCause() その例外を返します Runnable/Callable 投げた。

また、それが別の例外をスローします Runnable/Callable キャンセルされた。

のソースコードを見ました FutureTask そして、どこで見つけることができませんでした setException 呼ばれています。
あります innerSetException からの方法 FutureTask.Sync (の内部クラス FutureTask)それはanの場合に呼び出されています Throwable 実行方法によって投げられる。この方法も呼び出されています setException.
したがって、Javadocが正しくない(または理解するのが非常に難しい)ように縫い目があります。

3つの標準的な方法と1つの即興の方法があります。 1. uncedexceptionhandlerを使用し、作成されたスレッドのcoutexceptionhandlerを設定します。

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(Thread t, Throwable ex) {..}}

*しかし、制限はスレッドで投げられる例外をキャッチすることですが、将来のタスクの場合、それは飲み込まれます。 2.使用します afterExecute この目的のために特別に提供されているフックを使用してカスタムスレッドプールエクセクターを作成した後。 shoodpoolexecutorのコードを調べて、submit> executeを介して(workqueueがあります、 workQueue.offer)、タスクが作業キューに追加されます

   final void runWorker(Worker arg0) {
  Thread arg1 = Thread.currentThread();
  Runnable arg2 = arg0.firstTask;
  ..
     while(arg2 != null || (arg2 = this.**getTask()**) != null) {
        arg0.lock();
        ..
        try {
           this.beforeExecute(arg1, arg2);
           Object arg4 = null;
           try {
              arg2.run();
           } catch (RuntimeException arg27) {
             ..
           } finally {
              this.**afterExecute**(arg2, (Throwable)arg4);
           }

  }

getTask() {..
 this.workQueue.**poll**();
..}
  1. 次に、3つ目はコールメソッド内で単純なトライキャッチを使用することですが、ここで例外をキャッチすることはできません。

  2. 回避策は、呼び出し資金をリリースする工場であるTaskFactoryの呼び出しメソッドからすべての呼び出しメソッドを呼び出しています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top