ScheduledExecutorFactoryBean忽略异常继续执行
ScheduledExecutorFactoryBean忽略异常继续执行
程序中有一个定时任务,每10分钟把满足条件的任务从一个表迁移到另一张表,程序启动的时候数据库异常了一段时间,之后数据库恢复了。但是通过观察,发现此定时任务挂掉了,再也没有重启起来。
解决此问题的办法是要在任务线程的run方法中中捕获runtime异常,如果使用ScheduledExecutorFactoryBean,只要配置continueScheduledExecutionAfterException属性为true即可。Spring文档描述的很清楚:
setsup a JDK 1.5 ScheduledExecutorService
(bydefault: ScheduledThreadPoolExecutor
asimplementation) and exposes it for bean references.
Allowsfor registration of ScheduledExecutorTasks
,automatically starting the ScheduledExecutorService
oninitialization and cancelling it on destruction of the context. Inscenarios that just require static registration of tasks at startup,there is no need to access the ScheduledExecutorService
instanceitself in application code.
Notethat ScheduledExecutorService
usesa Runnable
instancethat is shared between repeated executions, in contrast to Quartzwhich instantiates a new Job for each execution.
WARNING: Runnables
submittedvia a native ScheduledExecutorService
areremoved from the execution schedule once they throw an exception. Ifyou would prefer to continue execution after such an exception,switch thisFactoryBean's"continueScheduledExecutionAfterException"
propertyto "true
对于定时任务,java原生支持有Timer,和ScheduledExecutor,前文中已经有介绍,参见:
http://blog.csdn.net/xiaojianpitt/article/details/7659422
如果使用spring的话,可以使用org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean,完全超越ScheduledExecutor。
ScheduledExecutorFactoryBean使用ScheduledThreadPoolExecutor
作为内部实现,定时调用使用
ScheduledThreadPoolExecutor
的方法
.
但是continueScheduledExecutionAfterException如何让异常任务继续运行的呢?代码是最好的说明:我们可以跟踪其源代码来找出:
protected Runnable getRunnableToSchedule(ScheduledExecutorTasktask) {
return this.continueScheduledExecutionAfterException
? new DelegatingErrorHandlingRunnable(task.getRunnable(),TaskUtils.LOG_AND_SUPPRESS_ERROR_HANDLER)
: newDelegatingErrorHandlingRunnable(task.getRunnable(),TaskUtils.LOG_AND_PROPAGATE_ERROR_HANDLER);
}
我们可以看到,如果我们设置了在异常之后继续执行任务,那么在实现中对Runnable进行了封装,封装类为DelegatingErrorHandlingRunnable,我们继续追踪其源代码:
publicclass DelegatingErrorHandlingRunnable implements Runnable{
…
public void run(){
try{
this.delegate.run();
}catch(Throwable ex){
this.errorHandler.handleError(ex):
}
}
…
}
注意这个DelegatingErrorHandlingRunnable实现了Runnable接口,作为原始任务的代理,需要注意的是run里面的trycatch 对异常的处理,在这里catch了Throwable异常(具体可见java异常结构),这java异常的基类,包括Error和RuntimeException所有的java异常都被捕获,之后交给了errorHandler处理,ErrorHandler可以继续抛出异常或者不抛出,其中TaskUtils.LOG_AND_SUPPRESS_ERROR_HANDLER只是log打印异常,TaskUtils.LOG_AND_PROPAGATE_ERROR_HANDLER要继续抛出runtimeException。
TiskUtils
代码如下:
public
static
final
ErrorHandlerLOG_AND_SUPPRESS_ERROR_HANDLER =
new
LoggingErrorHandler();
…
.
static class LoggingErrorHandler implements ErrorHandler {
private final Log logger =LogFactory.getLog(LoggingErrorHandler.class);
public void handleError(Throwable t) {
if (logger.isErrorEnabled()) {
logger.error("Unexpected error occurred in scheduledtask.", t);
}
}
}
….
static class PropagatingErrorHandler extends LoggingErrorHandler {
public void handleError(Throwable t) {
super.handleError(t);
ReflectionUtils.rethrowRuntimeException(t);
}
}
ReflectionUtils代码如下:
public static void rethrowRuntimeException(Throwable ex) {
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
if (ex instanceof Error) {
throw (Error) ex;
}
handleUnexpectedException(ex);
}
ScheduledExecutorFactoryBean忽略异常继续执行的更多相关文章
- Effective Java 第三版——77. 不要忽略异常
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- 异常依然执行{try..catch语句块..}的后续代码
测试异常依然执行{try..catch语句块..}的后续代码: private static Integer testThrows() throws Exception{ Integer result ...
- 第二讲shiro异常及执行流程
在认证过程中,有一个父异常为:AuthenticationException 该异常有几个子类,分别对应不同的异常情况: (1)DisabledAccountException:账户失效异常 (2)E ...
- python 如何跳过异常继续执行
使用try...except...语句,类似于if...else...,可以跳过异常继续执行程序,这是Python的优势 用法如下: 1 2 3 4 5 6 try: # 可能会 ...
- promise抛异常,执行队列
//promise抛出异常 new Promise((resolve,reject)=>{ resolve("成功") }).then(res=>{ if(res != ...
- YAML_07 有报错信息,告诉你错误忽略,继续执行下面的命令
ansible]# vim user5.yml --- - hosts: cache remote_user: root vars: user: bb tasks: - sh ...
- PHPDocumentor2.8.5 安装,使用及快速上手
PHPDocumentor当前版本是phpDocumentor-2.8.5.tgz 关于PHPDocumentor有什么用,还有其历史,我就不介绍了,直接进入正题.老版本的叫PHPDoc,从1.0开始 ...
- java实训 :异常(try-catch执行顺序与自定义异常)
关键字: try:执行可能产生异常的代码 catch:捕获异常 finally:无论是否发生异常代码总能执行 throws:声明方法可能要抛出的各种异常 throw:手动抛出自定义异常 用 try-c ...
- C#WinForm程序异常退出的捕获、继续执行与自动重启
本文参考网上搜索的信息,并做了适当修改可以让捕捉到异常之后阻止程序退出. 另给出了通过命令行自动重启的方法. 如果一个线程里运行下面的代码 ; / a; 将会导致程序自动结束,而且没有任何提示信息 但 ...
随机推荐
- 在使用Fake framework的时候,为什么有一些函数没有生产mock呢?
在使用Visual studio 2012 的Fake framework 做单元测试的时候,你会发现有一些函数没有生产Stub 或者 Shim的版本,这可能是由于Fake的一些限制导致的,但如何知道 ...
- JS数据类型&&typeof&&其他
1. 5种基本数据类型: 1. String 2. Number 3. Boolean 4. Undefined 5. Null 2. 1种复杂数据类型:Object 3. 检测变量的数据类型:typ ...
- [BZOJ 4103] [Thu Summer Camp 2015] 异或运算 【可持久化Trie】
题目链接:BZOJ - 4103 题目分析 THUSC滚粗之后一直没有写这道题,从来没写过可持久化Trie,发现其实和可持久化线段树都是一样的.嗯,有些东西就是明白得太晚. 首先Orz ZYF-ZYF ...
- zepto源码学习-03 $()
在第一篇的时候提到过关于$()的用法,一个接口有很多重载,用法有很多种,总结了下,大概有一以下几种 1.$(selector,context?) 传入一个选择器返回一个zepto对象 2.$(func ...
- HDU 2045 不容易系列之(3)—— LELE的RPG难题(递推)
点我看题目 题意 : 中文题不解释. 思路 :先算了第3个第4个,算的时候发现只要在已经枚举出来的前边的状态中往后添加字母就行了,如果两个的都已经表示出来了,那第三个就可以在每个第二个后边加一个,在 ...
- Java中对List集合的排序
方法一: 第一种方法,就是list中对象实现Comparable接口,代码如下: 实体类: public class Person implements Comparable<Person> ...
- Android ListView(Selector 背景图片)
listview0.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmln ...
- *[codility]Number-of-disc-intersections
http://codility.com/demo/take-sample-test/beta2010/ 这题以前做的时候是先排序再二分,现在觉得没有必要.首先圆可以看成线段,把线段的进入作为一个事件, ...
- 浅谈HTTP中Get与Post的区别/HTTP协议与HTML表单(再谈GET与POST的区别)
HTTP协议与HTML表单(再谈GET与POST的区别) GET方式在request-line中传送数据:POST方式在request-line及request-body中均可以传送数据. http: ...
- Linux 信号signal处理机制
信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念.Linux对信号机制的大致实现方法.如何使用信号,以及有关信号的几个系统调用. 信号机制是进程之间相互传递消息的一种方法,信号全 ...