ThreadPools中的exception处理
我有一个ScheduledThreadPoolExecutor似乎在吃exception。 如果提交的Runnable引发exception,我希望执行程序服务通知我。
例如,我想下面的代码至less打印IndexArrayOutOfBoundsException的stackTrace
threadPool.scheduleAtFixedRate( new Runnable() { public void run() { int[] array = new array[0]; array[42] = 5; } }, 1000, 1500L, TimeUnit.MILLISECONDS);
作为一个侧面的问题。 有没有办法为ScheduledThreadPoolExecutor编写一个通用的try catch块?
//////////原文问题结束//////////////
正如所build议的,以下装饰工程运作良好。
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(); } } }
我刚才写了一个关于这个问题的小贴子 。 你有两个select:
- 使用Colin Herbert提供的解决scheme
- 使用Mark Peters 解决scheme的修改版本,而不是分配
UncaughtExceptionHandler
而是将每个提交的runnable包装到您自己的runnable中,在try-catch-block中执行(调用run
)真正的runnable。
编辑
正如Mark指出的那样,将传递给ScheduledExecutorService
的Runnable
而不是传递给ThreadFactory
的Runnable
包装起来非常重要。
警告 :此方法不适用于预定的线程池执行程序。 这个答案与其他线程池执行者的相关性已经被取消了。 看威利的答案 。
重写ThreadFactory
为Thread提供一个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; } }
您可以通过调用scheduleAtFixedRate()
来使用Future
的get()
方法。 如果在线程执行过程中发生怀疑,它将抛出ExecutionException
exception。
你也可以使用Spring框架中的ThreadPoolTaskScheduler
,它提供了一个设置error handling器的方法,并为你做了所有的包装。 默认行为取决于任务的types:
如果提供的ErrorHandler
不为空,它将被使用。 否则,默认情况下,重复任务将被错误抑制,而一次性任务会默认传播错误,因为这些错误可能是通过返回的Future
来预期的。 在这两种情况下,都会logging错误。
如果你只想使用包装部分,而不是你可以使用的TaskScheduler
TaskUtils.decorateTaskWithErrorHandler(task, errorHandler, isRepeatingTask)
TaskScheduler
内部使用。
您可以对ScheduledThreadPoolExecutor进行子类化,并重写afterExecute方法来处理您提交的任何types的Runnable的exception和错误。
考虑在您的ScheduledThreadPoolExecutor类中添加一个静态事件,以便在引发exception时调用您的任何任务。 这样,您可以利用该事件来捕获和处理线程中发生的exception。