线程池中的异常处理
我有一个 ScheduledThreadPoolExecutor 似乎正在吃异常。我希望我的执行器服务在提交的 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();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我写了一个小不久前发布了关于此问题的帖子。您有两种选择:
UncaughtExceptionHandler 将每个提交的 runnable 包装到您自己的 runnable 中,该 runnable 在 try-catch 块内执行(调用
run
)真正的 runnable。编辑
正如 Mark 所指出的,包装传递给
ScheduledExecutorService
的Runnable
而不是传递给ThreadFactory
的 Runnable 非常重要。I wrote a small post about this problem a while ago. You have two options:
UncaughtExceptionHandler
you wrap each submitted runnable into a runnable of your own which executes (callsrun
) the real runnable inside a try-catch-block.EDIT
As pointed out by Mark, it's important to wrap the
Runnable
passed toScheduledExecutorService
instead of the one passed to theThreadFactory
.警告:此方法不适用于预定线程池执行器。由于与其他线程池执行器的相关性,该答案已被取消删除。请参阅威利的回答。
重写 ThreadFactory 为线程提供 UncaughtExceptionHandler:
Warning: This method is not applicable to scheduled thread pool executors. This answer has been undeleted for its relevance to other thread pool executors. See Willi's answer.
Override the
ThreadFactory
to give Threads an UncaughtExceptionHandler:您可以使用通过调用
scheduleAtFixedRate()
获得的Future
中的get()
方法。如果线程执行期间发生异常,它将抛出 ExecutionException。You can use the
get()
method from theFuture
you're getting by callingscheduleAtFixedRate()
. It will throw anExecutionException
if an exeception occurred during the thread execution.您还可以使用 “nofollow">Spring 框架,它公开了一个方法来设置错误处理程序并为您完成所有包装。默认行为取决于任务类型:
如果提供的
ErrorHandler
不为 null,则将使用它。否则,默认情况下,重复任务将抑制错误,而默认情况下一次性任务将传播错误,因为这些错误可能是通过返回的Future
预期的。在这两种情况下,都会记录错误。如果您只想使用包装部分而不是
TaskScheduler
,则可以使用TaskScheduler
在内部使用的内容。You could also use a
ThreadPoolTaskScheduler
from the Spring Framework, which exposes a method to set an error handler and does all the wrapping for you. The default behavior depends on the type of task:If the provided
ErrorHandler
is not null, it will be used. Otherwise, repeating tasks will have errors suppressed by default whereas one-shot tasks will have errors propagated by default since those errors may be expected through the returnedFuture
. In both cases, the errors will be logged.If you only want to use the wrapping part and not the
TaskScheduler
you can usewhich the
TaskScheduler
uses internally.您可以子类化 ScheduledThreadPoolExecutor 并覆盖 afterExecute 方法来处理您提交的任何类型的 Runnable 的异常和错误。
You can subclass ScheduledThreadPoolExecutor and override the afterExecute method to handle exceptions and errors for any kind of Runnable that you submit.
考虑在您的 ScheduledThreadPoolExecutor 类中添加一个静态事件,如果抛出异常,您的任何任务都可以调用该事件。这样,您就可以利用该事件来捕获和处理线程中发生的异常。
Consider adding a static event in your ScheduledThreadPoolExecutor class that any of your tasks can call if an exception is thrown. That way, you can leverage that event to capture and handle the exceptions that occur within your threads.