关于quartz可以设置为串行执行的比较详细说明

quartz本身和spring都提供了设置quartz任务串行的解决办法。

没有用spring的情况:

方法1,task实现StatefulJob接口。这个接口在quartz2.0的时候作废了,现在建议使用注解的方式完成串行的配置,不过这个接口依然有效,因为2.0版本的这个接口使用了@DisallowConcurrentExecution和@PersistJobDataAfterExecution的注解。

方法2,注解@DisallowConcurrentExecution。这个代表设置该任务为串行执行。

另外:注解@PersistJobDataAfterExecution。这个代表该任务可以支持在任务间使用JobDataMap传递信息,在任务结束时保存信息,不必设置为串行。但如果并行任务使用该注解可能会让JobDataMap中的内容产生不可预知的结果,所以还是强烈建议使用该注解的同时使用@DisallowConcurrentExecution注解。

然后任务的定义大概是这样的:

@PersistJobDataAfterExecution

@DisallowConcurrentExecution

public class BillingBillTask extends Job {

 

         publicstatic int test=1;

        

         publicvoid executeInternal()throws JobExecutionException {

                   test++;

                   JobDataMapmap=arg0.getJobDetail().getJobDataMap();

                   if(map.get("key")==null){

                            System.out.println("key==null");

                            map.put("key","123");

                   }else{

                            System.out.println("key!=null");

                            System.out.println(map.get("key"));

                   }

         }

}

 

用了spring和quartz结合的情况:

方法1,使用前文没用spring的方法,依然适用。

方法2,spring-quartz.xml配置文件修改。

spring提供了几个使用quartz的类:

第一个类:JobDetailFactoryBean。

使用这个类,配置文件大概是这样的:

<bean id="jobDetail7" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">

                   <propertyname="jobClass"value="com.dangdang.tms.job.schedule.bms.BillingBillTask"></property>

                   <propertyname="durability" value="true" />

         </bean>

         <beanid="cronTriggerBean7" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">

                   <propertyname="jobDetail" ref="jobDetail7"></property>

                   <propertyname="cronExpression" value="0/5 * * * * ?"></property>

         </bean>

task的定义大概是这样的:

public class BillingBillTask extends QuartzJobBean{

 

         publicstatic int test=1;

        

         @Override

         publicvoid executeInternal(JobExecutionContext arg0)throws JobExecutionException {

                   test++;

JobDataMap map=arg0.getJobDetail().getJobDataMap();

                   if(map.get("key")==null){

                            System.out.println("key==null");

                            map.put("key","123");

                   }else{

                            System.out.println("key!=null");

                            System.out.println(map.get("key"));

                   }

         }

}

 

注:

1,  task类需要继承QuartzJobBean。

2,  这个类在spring中没有提供让quartz作业串行执行的配置。如果用了这个类还要串行执行的话,使用@DisallowConcurrentExecution注解吧。

3,  如果设置了串行执行,JobDetail中的JobDataMap可以在多次执行的任务中传递内容,不会因为任务结束而清空。

 

第二个类:MethodInvokingJobDetailFactoryBean。

使用这个类,配置文件大概是这样的:

<bean id="jobDetail7"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

                   <propertyname="targetObject" ref="billingBillTask"></property>

                   <propertyname="targetMethod" value="executeInternal" />

                   <propertyname="concurrent" value="false" />

         </bean>

         <beanid="billingBillTask"class="com.dangdang.tms.job.schedule.bms.BillingBillTask"/>

         <beanid="cronTriggerBean7" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">

                   <propertyname="jobDetail" ref="jobDetail7"></property>

                   <propertyname="cronExpression" value="0/5 * * * * ?"></property>

         </bean>

 

task的定义大概是这样的:

public class BillingBillTask{

         public static int test=1;

         publicvoid executeInternal()throws JobExecutionException {

                   test++;

         }

}

 

注:

1,<propertyname="targetObject"ref="billingBillTask"></property>中的ref不能直接写成value=”com.dangdang.tms.job.schedule.bms.BillingBillTask”这种形式,必须得下面再写个id=”billingBillTask”,原因没研究过。

2,这种配置中设置的executeInternal方法必须是无参数的,如果设置了参数就会报找不到方法的异常。

4,  这种配置中,即使设置了串行执行,无法使用JobDataMap来在串行的任务中传递参数,如果需要传递参数的话,另想办法。比如定义一个静态变量之类的。

 

有misfireThreshold参数,定义过期时间。

quartz中默认的misfireThreshold是60000,也就是60秒。

我对这个参数的理解是,一个在串行的时候后面任务被阻碍多久就放弃的参数,比如:

设置该参数为10秒,定时任务串行执行,20秒执行一次。

如果第一个任务0秒开始执行,执行到第25秒结束,第二个定时任务应该20s时开始执行,但拖到了25s,与执行时间间隔了5秒,小于配置的10秒,那么第二个定时任务会在第25s,也就是第一个定时任务结束的当时就开始执行。

如果第一个任务0秒开始执行,执行到第35秒结束,第二个定时任务应该20s开始执行,但拖到了35秒,与执行时间间隔了15秒,大于配置的10秒,那么20s开始执行的任务会放弃,而按照配置中的下次执行时间也就是第40s开始执行。

 

这个参数在quartz中的配置是这样的:

org.quartz.jobStore.misfireThreshold: 60000

在spring中的配置是这样的:(试了一下没有成功,还是按照60秒放弃任务,原因未知)
<bean id="trigger" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

                   <propertyname="triggers">

                            <list>

                                     <refbean="cronTriggerBean7" />

                            </list>

                   </property>

                   <propertyname="jobFactory">

                            <beanclass="com.dangdang.tms.job.schedule.AutowiredJobFactory"></bean>

                   </property>   

       <property name="applicationContextSchedulerContextKey"value="applicationContextKey" />

       <property name="quartzProperties">  

           <props>

                <propkey="org.quartz.jobStore.misfireThreshold">10000</prop>  

           </props>  

       </property>

</bean>

另外,对于因为串行而错过执行时间的任务,quartz有多种策略,比如:

withMisfireHandlingInstructionDoNothing:不立即触发,等下次执行时间执行

withMisfireHandlingInstructionFireAndProceed:立即触发执行

还有很多其他规则奇葩看起来十分眼晕的策略,没深入研究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值