少年阿宾

那些青春的岁月

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks
1、StatefulJob
implements StatefulJob使Job成为有状态的,顺序执行 
同一个有状态的job实例不存在并发,无状态的job的并发数由上面配置的线程数决定。不想并发的话,设置成1,第二个线程在前一个执行完以后触发执行。
线程数大于1时,如果存在空闲线程,则到执行时间点即触发执行。

2、
MethodInvokingJobDetailFactoryBean
MethodInvokingJobDetailFactoryBean的并发问题
大家在使用quartz的时候,一般只设置了“targetObject”和“targetMethod”,MethodInvokingJobDetailFactoryBean类默认是并发执行的,这时候如果不设置“concurrent”为false,很可能带来并发或者死锁的问题,而且几率较小,不容易复现,请大家使用的时候注意设置“concurrent”。
 
    <bean id="cpm.MessageJobFactoryBean" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="cpm.MessageJob"/>
        <property name="targetMethod" value="execute"/>
        <property name="concurrent" value="false"/>
    </bean>
concurrent   同时发生
 concurrent:对于相同的JobDetail,当指定多个Trigger时, 很可能第一个job完成之前,第二个job就开始了。
 定concurrent设为false,多个job不会并发运行,第二个job将不会在第一个job完成之前开始




防止job并行运行的几种解决方案 
一、JOB State 
在通过MethodInvokingJobDetailFactoryBean在运行中动态生成的Job,配置的xml文件有个concurrent属性,表示job是否可以并行运行:如果一个job的业务处理发费的时间超过了job的启动的间隔时间(repeatInterval),这个属性非常有用。如果为false,那么,在这种情况下,当前job还在运行,那么下一个job只能延时运行。如果为true,那么job就会并行运行。在实际的应用中应该配置为true/false,要根据需要了(废话)。 
二、如果通过继承QuartzJobBean实现job的话,默认情况下QuartzJobBean是implements org.quartz.Job接口的,也就是说job示例是stateless的,会出现前面所述的并行情况。而代码中却要求job任务必需串行,解决办法:在job子类中继续implements org.quartz.StatefulJob。那么这个job实例变成了Stateful,job任务也就是串行的了。
注: 
在Quartz中,如果实现org.quartz.Job接口,那么这个job是stateless的,job实例的参数不能在多个任务之间共享,如果实现org.quartz.StatefulJob,这个job是个单例的,job实例的属性可以从当前任务传递到下一个任务。 


spring和quartz的整合对版本是有要求的。
spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会出错。

至于原因,则是spring对于quartz的支持实现,org.springframework.scheduling.quartz.CronTriggerBean继承了org.quartz.CronTrigger,在quartz1.x系列中org.quartz.CronTrigger是个类,而在quartz2.x系列中org.quartz.CronTrigger变成了接口,从而造成无法用spring的方式配置quartz的触发器(trigger)。

在Spring中使用Quartz有两种方式实现:第一种是任务类继承QuartzJobBean,第二种则是在配置文件里定义任务类和要执行的方法,类和方法可以是普通类。很显然,第二种方式远比第一种方式来的灵活。



MethodInvokingJobDetailFactoryBean中concurrent和shouldRecover属性的作用
解释 concurrent为true,则允许一个QuartzJob并发执行,否则就是顺序执行。例如QuartzJob A执行时间为15秒,配置为每10秒执行一次;如果concurrent为true,则0秒的时候启动一次A,10秒的时候再启动一次A,20秒的时候再启动一次A,不管前面启动的A有没有执行完;如果concurrent为false,则0秒的时候启动一次A,15秒的时候A执行完毕,再第二次启动A。
shouldRecover属性为true,则当Quartz服务被中止后,再次启动或集群中其他机器接手任务时会尝试恢复执行之前未完成的所有任务。例如QuartzJob B,在每次00秒的时候启动,假如在03:00的任务执行完之后服务器1被中止,服务器2在05:15的时候才接手;如果shouldRecover属性为true,则服务器2会尝试着补回原来在04:00和05:00的时候应该做的任务,如果shouldRecover属性为false,则服务器2只会从06:00的时候再执行B。


Quartz集群只支持JDBCJobStore存储方式,而MethodInvokingJobDetailFactoryBean不能序列化存储job数据到数据库,
重写 quartz 的 QuartzJobBean 类 
原因是在使用 quartz+spring 把 quartz 的 task 实例化进入数据库时,会产生: serializable 的错误,原因在于:
这个 MethodInvokingJobDetailFactoryBean 类中的 methodInvoking 方法,是不支持序列化的,因此在把 QUARTZ 的 TASK 序列化进入数据库时就会抛错。网上有说把 SPRING 源码拿来,修改一下这个方案,然后再打包成 SPRING.jar 发布,这些都是不好的方法,是不安全的。
必须根据 QuartzJobBean 来重写一个自己的类 。


posted on 2015-07-26 01:39 abin 阅读(2090) 评论(0)  编辑  收藏 所属分类: quartz

只有注册用户登录后才能发表评论。


网站导航: