2011-01-05 3 views
0

私はこれらの行に沿っていくつかの議論を見ましたが、私の質問に対する具体的な答えはありません。私はスレッドが未知の例外のために死んだときにタスクを再開したい。死んでいるスレッドのUncaughtExceptionHandlerセット内からpool.execute(runnable)を呼び出すことは安全ですか?UncaughtExceptionHandler内からタスクを再実行しますか?

理想的には、throwableがRuntimeExceptionの場合は、プールにrunnableを再送信するだけです。


pool = Executors.newFixedThreadPool(monitors.size(), new ThreadFactory() { 
    @Override 
    public Thread newThread(Runnable r) { 
     Thread thread = new Thread(r); 
     threadMap.put(thread, (Monitor)r); 
     thread.setName(((Monitor)r).getClusterName() + "-monitor"); 
     thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { 
      @Override 
      public void uncaughtException(Thread th, Throwable t) { 
       logger.error("Uncaught exception in thread: " + th.getName(), t); 
       if (t instanceof RuntimeException) { 
        Monitor m = threadMap.get(th); 
        if (m != null && m.runCount() < restartMax) { 
         logger.error("Restarting monitor due to uncaughtException: " + m.getClusterName()); 
         pool.execute(m); 
        }      } 
      }     
     }); 
     return thread; 
    }   
}); 

これを行うには、より良い方法や安全な方法がありますか?

ありがとうございます!

答えて

1

最も安全なオプションは、それが致命的なランタイム例外を投げることだけです。ランタイム例外を安全に無視できる場合、なぜそれが捕捉されずに継続されているのですか?

あなたのスレッドマップはThreadLocalに似ているようですが、あるタスクでrestartMaxをすべて使用すると、タスクは再開されません。

私がこれを行う方法は、実行中のRunnableをラップすることです。

public void submit(final Runnable runnable, final int restartMax) { 
    pool.submit(new Runnable() { 
     public void run() { 
      for(int i=0;i<restartMax;i++) 
       try { 
        runnable.run(); 
        break; 
       } catch (Exception e) { 
        log.error("Exception", e); 
       } 
     } 
    } 
} 
+0

threadMapは、例外を指定してスレッドに対応するMonitor/Runnableを取得できるようにするためのものです。 restartMaxは、永続的なエラーが直ちに発生するスレッドを無期限に再起動しないようにすることです。このメカニズムは、明示的に処理されていない一時的な例外から回復するためのものです。 – batkins

0

あなたのコードサンプルは、あなたが取り組もうとしている仕事をしません。 ThreadFactoryに渡される実行可能ファイルは、タスクの実行可能ファイルではなく、ThreadPoolExecutorによって使用される内部実行可能ファイルです。

代わりにafterExecute()メソッドをオーバーライドすることを検討してください。このメソッドは常に呼び出され、最初の引数は実行可能になり、2番目の(Throwable)引数にはキャッチされない例外が含まれます。ただし、afterExecute()は、タスクが明示的にFutureTaskでラップされている場合、またはsubmit()によって間接的にラップされている場合は、ではなく、は例外を報告します。ですから、afterExecute()はexecute()を介したsubmissionでのみ動作します。

protected void afterExecute(Runnable r, Throwable t) { 
    super.afterExecute(r, t); 
    if (t != null) { 
     Monitor m = (Monitor)r; 
     if (m.runCount() < restartMax) { 
      logger.error("Restarting monitor due to uncaughtException: " 
        + m.getClusterName()); 
      execute(m); // exception handling omitted 
     } 
    } 
} 
+0

はい、私はすぐにその正確な問題に直面しました。当面は伝統的な新しいThread/setUncaughtExceptionHandler/startシーケンスを使用しています。それはあなたがスレッドからRunnableにアクセスすることができないことは奇妙で近視眼的なようです。私はあなたの提案を調べます。私はFutureTaskも提出もしていないので、これはうまくいくはずです。ありがとう! – batkins

+0

スレッドがあなたのrunnableを渡して作成されたとしても、それは単にスレッドの作成をトリガーした**最初の**タスクであることに注意してください。スレッドは長期間使用され、複数のタスクを実行します。したがって、RuntimeExceptionが確実に発生する実際の実行可能ファイルを取得することはできません。 – sjlee

関連する問題