我有一个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();
}
}
}
答案 0 :(得分:24)
我刚才写了一篇关于这个问题的小post。您有两种选择:
答案 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 类中添加一个静态事件,如果抛出异常,您的任何任务都可以调用。这样,您可以利用该事件来捕获和处理线程中发生的异常。