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 = newLoggingErrorHandler();

.

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忽略异常继续执行的更多相关文章

  1. Effective Java 第三版——77. 不要忽略异常

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  2. 异常依然执行{try..catch语句块..}的后续代码

    测试异常依然执行{try..catch语句块..}的后续代码: private static Integer testThrows() throws Exception{ Integer result ...

  3. 第二讲shiro异常及执行流程

    在认证过程中,有一个父异常为:AuthenticationException 该异常有几个子类,分别对应不同的异常情况: (1)DisabledAccountException:账户失效异常 (2)E ...

  4. python 如何跳过异常继续执行

    使用try...except...语句,类似于if...else...,可以跳过异常继续执行程序,这是Python的优势 用法如下: 1 2 3 4 5 6 try:            # 可能会 ...

  5. promise抛异常,执行队列

    //promise抛出异常 new Promise((resolve,reject)=>{ resolve("成功") }).then(res=>{ if(res != ...

  6. YAML_07 有报错信息,告诉你错误忽略,继续执行下面的命令

    ansible]# vim user5.yml --- - hosts: cache   remote_user: root   vars:     user: bb   tasks:    - sh ...

  7. PHPDocumentor2.8.5 安装,使用及快速上手

    PHPDocumentor当前版本是phpDocumentor-2.8.5.tgz 关于PHPDocumentor有什么用,还有其历史,我就不介绍了,直接进入正题.老版本的叫PHPDoc,从1.0开始 ...

  8. java实训 :异常(try-catch执行顺序与自定义异常)

    关键字: try:执行可能产生异常的代码 catch:捕获异常 finally:无论是否发生异常代码总能执行 throws:声明方法可能要抛出的各种异常 throw:手动抛出自定义异常 用 try-c ...

  9. C#WinForm程序异常退出的捕获、继续执行与自动重启

    本文参考网上搜索的信息,并做了适当修改可以让捕捉到异常之后阻止程序退出. 另给出了通过命令行自动重启的方法. 如果一个线程里运行下面的代码 ; / a; 将会导致程序自动结束,而且没有任何提示信息 但 ...

随机推荐

  1. ionic+angulajs

    基于ionic+angulajs的混合开发实现地铁APP 项目源码地址:https://github.com/zhangxy1035/SubwayMap 一.项目简介 在该项目中的地铁app是基于io ...

  2. win2003 sp2+iis 6.0上部署.net 2.0和.net 4.0网站的方法

    网站环境 IIS6.0,操作系统Windows server2003 sp2,服务器之前已经部署了.net 2.0和asp的网站,现在要部署新开发的.net 4.0网站.本来认为很简单,却遇到了很多问 ...

  3. python与编码

    Python中的文字对象 Python 3.x中处理文字的对象有str, bytes, bytearray. bytes和bytearray可以使用除了用作格式化的方法(format, format_ ...

  4. QR code 乱谈(一)

    缘由 促使草人写这一系列(将会是)文章的原因是二维码现在很流行,很容易接触到,而且二维码又是那么容易就生成——就不说有很多在线的生成器,许多应用软件也都有生成二维码的功能,比如Firefox浏览器.Q ...

  5. 回首Java(始)

    自接触Java开始,已然5载春秋. 如今每每在深入学习过程中,时刻感到力不从心. It's time!该拾起J2SE基石. 平地高楼,日积跬步.根底不坚实,如今才寸步维艰. 回头再温故.

  6. location.hash && location.href

    hash:设置或获取 href 属性中在井号“#”后面的分段. href:设置或获取整个URL为字符串. 通过下面的测试你会发现区别,将代码放到你的HTML中,然后用浏览器打开,测试步骤: 点击“超链 ...

  7. 来看看Meteor的功能

    看了一上午,感觉这确实比所谓传统的APP开发,有很多不一样的地方. 记录下来: simple-todos.css /* CSS declarations go here */ /* CSS decla ...

  8. HDOJ多校联合第四场

    B题: C题:仅由'A','G','C','T',4个字母组成,给定一个字符串S,|S|<=15,给定一个整数m,以m为长度且仅含4种字母的字符串T,求LCS(S,T)为0,1,2,3....| ...

  9. PDF文件结构

    概述PDF是一种不依赖应用程序软件.硬件和操作系统的文件格式.PDF页包含文本.图形和图像.页面外观由内容流(content stream)描述,内容流包含一些列图形对象(graphics objec ...

  10. javaweb学习总结(三十九)——数据库连接池

    一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...