web-dev-qa-db-ja.com

ThreadPoolsでの例外処理

例外を食べているように見えるScheduledThreadPoolExecutorがあります。送信したRunnableが例外をスローした場合に、Executorサービスから通知を受けたい。

たとえば、次のコードでは、少なくともIndexArrayOutOfBoundsExceptionのstackTraceを出力してください。

threadPool.scheduleAtFixedRate(
  new Runnable() {
    public void run() {
      int[] array = new array[0];
      array[42] = 5;
    }
  },
  1000,
  1500L,
  TimeUnit.MILLISECONDS);

副次的な質問として。 ScheduledThreadPoolExecutorの一般的なtry catchブロックを作成する方法はありますか?

/////////// END OF ORIGINAL QUESTION //////////////

提案されているように、次のデコレーターはうまく機能します。

public class CatcherTask implements Runnable{

    Runnable runMe;

    public CatcherTask(Runnable runMe) {
        this.runMe = runMe;
    }

    public void run() {
        try {
            runMe.run();
        } catch (Exception ex){
            ex.printStackTrace();
        }
    }
}
43
Ivan

この問題について少し前に post を書きました。次の2つのオプションがあります。

  1. Colin Herbertが提供する solution を使用するか、
  2. mark Peters solution の修正版を使用しますが、UncaughtExceptionHandlerを割り当てる代わりに、実際に実行される(runを呼び出す)独自の実行可能ファイルに実際の実行可能ファイルをラップしますtry-catch-block内で実行できます。

[〜#〜]編集[〜#〜]
マークが指摘したように、Runnableに渡されたものではなく、ScheduledExecutorServiceに渡されたThreadFactoryをラップすることが重要です。

24
whiskeysierra

警告:このメソッドは、scheduledスレッドプールエグゼキューターには適用されません。この回答は、他のスレッドプールエグゼキューターとの関連性から削除されていません。 Willi's answer を参照してください。

ThreadFactoryをオーバーライドして、スレッドにUncaughtExceptionHandlerを与えます。

ThreadPoolExecutor exec = new ThreadPoolExecutor...;

exec.setThreadFactory(new ExceptionCatchingThreadFactory(exec.getThreadFactory()));
//go on to submit tasks...


private static class ExceptionCatchingThreadFactory implements ThreadFactory {
    private final ThreadFactory delegate;

    private ExceptionCatchingThreadFactory(ThreadFactory delegate) {
        this.delegate = delegate;
    }

    public Thread newThread(final Runnable r) {
        Thread t = delegate.newThread(r);
        t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                e.printStackTrace();  //replace with your handling logic.
            }
        });
        return t;
    }
}
13
Mark Peters

get()を呼び出すことで、取得しているFutureからscheduleAtFixedRate()メソッドを使用できます。スレッドの実行中に例外が発生した場合は、ExecutionExceptionがスローされます。

5
Colin Hebert

Spring FrameworkThreadPoolTaskSchedulerを使用して、エラーハンドラーを設定するメソッドを公開し、すべてのラッピングを行うこともできます。デフォルトの動作は、タスクのタイプによって異なります。

提供されたErrorHandlerがnullでない場合、それが使用されます。それ以外の場合、繰り返しタスクにはデフォルトでエラーが抑制されますが、ワンショットタスクにはデフォルトでエラーが伝搬されます。これらのエラーは返されたFutureを介して予期されるためです。どちらの場合も、エラーがログに記録されます。

TaskSchedulerではなく、ラッピングパーツのみを使用する場合は、

TaskUtils.decorateTaskWithErrorHandler(task, errorHandler, isRepeatingTask)

TaskSchedulerが内部で使用します。

3
Johan Boberg

ScheduledThreadPoolExecutorをサブクラス化し、 afterExecute メソッドをオーバーライドして、送信するあらゆる種類のRunnableの例外とエラーを処理できます。

2
mryan