ThreadPools中的异常处理

时间:2010-10-06 18:31:42

标签: java exception-handling threadpool

我有一个ScheduledThreadPoolExecutor似乎正在吃Exception。如果提交的Runnable抛出异常,我希望我的执行程序服务通知我。

例如,我希望下面的代码至少打印出IndexArrayOutOfBoundsException的stackTrace

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

作为一个附带问题。有没有办法为ScheduledThreadPoolExecutor编写一般的try catch块?

//////////原始问题的结尾//////////////

正如所建议的那样,以下的装饰工作得很好。

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();
        }
    }
}

6 个答案:

答案 0 :(得分:24)

我刚才写了一篇关于这个问题的小post。您有两种选择:

  1. 使用Colin Herbert提供的solution
  2. 使用Mark Peters solution的修改版本,但不是分配UncaughtExceptionHandler而是将每个提交的runnable包装到您自己的runnable中,该runnable执行(调用run)里面的真实runnable一个试试拦截块。
  3. 修改
    正如Mark所指出的那样,将Runnable传递给ScheduledExecutorService而不是传递给ThreadFactory的传递是很重要的。

答案 1 :(得分:13)

警告:此方法不适用于预定线程池执行程序。这个答案因其与其他线程池执行程序的相关性而未被删除。请参阅Willi's answer

重写ThreadFactory,为Threads提供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;
    }
}

答案 2 :(得分:5)

您可以通过致电get()来使用Future获得的scheduleAtFixedRate()方法。如果在线程执行期间发生了异常,它将抛出ExecutionException

答案 3 :(得分:3)

您还可以使用Spring Framework中的ThreadPoolTaskScheduler,它会公开一种方法来设置错误处理程序并为您完成所有包装。默认行为取决于任务类型:

如果提供的ErrorHandler不为null,则将使用它。否则,重复任务将默认抑制错误,而一次性任务将默认传播错误,因为这些错误可能通过返回的Future来预期。在这两种情况下,都会记录错误。

如果您只想使用包装部件而不是TaskScheduler,则可以使用

TaskUtils.decorateTaskWithErrorHandler(task, errorHandler, isRepeatingTask)

TaskScheduler在内部使用。

答案 4 :(得分:2)

您可以继承ScheduledThreadPoolExecutor并覆盖afterExecute方法来处理您提交的任何类型的Runnable的异常和错误。

答案 5 :(得分:-1)

考虑在 ScheduledThreadPoolExecutor 类中添加一个静态事件,如果抛出异常,您的任何任务都可以调用。这样,您可以利用该事件来捕获和处理线程中发生的异常。