飞道的博客

探究 Spring 的定时任务配置

292人阅读  评论(0)

作者 | 郭朝兴

责编 | Elle

出品 | CSDN(ID:CSDNnews)

最近在项目开发中进行了一些Spring定时任务的开发工作,在开发过程中对Spring定时任务的配置方式进行了一些研究,现在对各种配置方式进行一个总结。Scheduled是Spring支持的定时任务配置方式,可以用注解或者配置文件的方式进行配置。

Quartz是一个强大的企业级任务调度框架,Spring中继承并简化了Quartz,它是一个开源的由OpenSymphony维护的项目,开发者能够在Java EE,或单独的Java SE应用中使用它。无论是简单的任务调度,还是复杂的企业级应用,Quartz都能够很好地胜任。

Quartz支持CronTriggerBean,SimpleTriggerBean两种模式,CronTriggerBean比 SimpleTriggerBean功能更强大,它能够控制任务执行的精确时间,比如,早上九点半需要执行某QuartzJobBean中给定的任务。

以下对不同的配置方式分别进行介绍。

通Scheduled注解或者xml配置的方式添加定时任务

ref 是定时任务的类在 Spring中的beanName,method是要执行的方法,fixed-delay 是上一个调用完成后,再次调用的延时,fixed-rate 是 上一个调用开始后,再次调用的延时(不用等待上一次调用完成),cron 是表达式,表示在什么时候进行任务调度。


   
  1. <task:scheduled-tasks scheduler= "scheduler" >
  2. <task:scheduled ref= "profitScheduler" method= "execute" cron= "0 0/2 * * * ?"      initial-delay= "5000" fixed-delay= "3600000" />
  3. </task:scheduled-tasks>
  4. <task:scheduler id= "scheduler" pool-size= "5" />

也可以采用注解的方式,在需要配置为定时任务的方法上添加@Scheduled(cron = "0 0 3 * * ?"),cron为定时任务表达式,cron表达式支持非常丰富的配置规则。


   
  1. @Component(“taskJob”)  
  2.     public class TaskJob { k
  3.         @Scheduled(cron =  "0 0 3 * * ?")  
  4.         public void job1() {  
  5.             System.out. println(“任务进行中。。。”);  
  6.         }
  7.     }

配置任务执行的线程池信息。task:scheduler用来配置任务调度线程池大小,调度线程在被调度任务完成前不会空闲;task:executor用来配置任务执行器的具体参数,pool-size 可以指定执行线程池的初始大小、最大大小,queue-capacity配置等待执行任务的队列容量,reject-policy当等待队列爆了时的策略,分为丢弃、有任务执行器直接执行等方式。  


   
  1.   <task:executor id= "executor" pool-size= "10-10000" queue-capacity= "5000" rejection-policy= "CALLER_RUNS"/>
  2.  <task:scheduler id= "scheduler" pool-size= "1000"/>
  3.  <task:annotation-driven executor= "executor" scheduler= "scheduler"/> 

CronTrigger配置方式

CronTrigger 支持比simpleTrigger更具体的调度,CronTrigger支持类似日历的重复间隔。CronTrigger 由MethodInvokingJobDetailFactoryBean、CronTriggerFactoryBean两个类支持。

MethodInvokingJobDetailFactoryBean配置需要定时执行的任务类和方法,targetObject为执行定时任务的bean,targetMethod为执行定时任务的bean中的方法。CronTriggerFactoryBean为定时任务的触发器,用来配置定时任务执行的时间表达式。


   
  1.   <bean id= "sycnMonitorBean" class= "org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  2.   <property name= "targetObject" ref= "monitorService" />
  3.   <property name= "targetMethod" value= "syncMonitor" />
  4.  </bean>
  5.  <bean id= "syncTrigger"
  6.   class= "org.springframework.scheduling.quartz.CronTriggerFactoryBean">
  7.   <property name= "jobDetail" ref= "sycnMonitorBean" />
  8.   <property name= "cronExpression" value= "0 */10 * * * ?" />
  9. </bean>

SimpleTigger配置方式

当需要在规定的时间执行一次或者以一定的时间间隔重复出发执行job时,SimpleTrigger 就可以满足要求。SimpleTrigger的属性有:开始时间、结束时间、重复次数、重复时间间隔。

如下示例:首先创建需要执行定时任务的bean,名字为quartzBean。然后配置该bean需要定时执行的方法。Concurrent参数用来配置是否同步执行。如果配置为true,则任务执行时,只有上次执行完成后,才可以进入下一次执行。

SimpleTriggerFactoryBean配置了触发器执行的策略,开始执行的延迟时间及执行的时间间隔。SchedulerFactoryBean用来管理任务计划,是任务的总的管理类。将lazy-init='false'那么容器启动就会执行调度程序。


   
  1.  <bean id= "quartzBean" class= "com.abchina.tao.scheduled.QuartzMain">
  2.   <property name= "scheduler" ref= "schedulerManager"></property>
  3.  </bean>
  4.  <!-- 定义jobdetail -->
  5.  <bean id= "quartzJobDetail" class= "org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  6.   <property name= "targetObject" ref= "quartzBean"></property>
  7.   <property name= "targetMethod" value= "startQuartz"></property>
  8.   <property name= "concurrent" value= "false" />
  9.  </bean>
  10.  <bean id= "quartzTrigger"
  11.  class= "org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
  12.   <property name= "jobDetail" ref= "quartzJobDetail"></property>
  13.   <property name= "startDelay" value= "1000"></property>
  14.   <property name= "repeatInterval" value= "300000"></property>
  15.  </bean>
  16.  <!-- 任务计划,总管理类-->
  17.  <bean id= "schedulerManager" lazy-init= "false" autowire= "no" class= "org.springframework.scheduling.quartz.SchedulerFactoryBean">
  18.  <property name= "triggers">
  19.   <list>
  20.    <ref bean= "quartzTrigger" />
  21.     </list>
  22.  </property>
  23.  </bean>

SimpleTrigger与CronTrigger高级应用场景

针对需要将定时任务配置为根据用户的实际运行需要,动态调整任务执行的计划,并准实时生效的情况。可以采用配置页面的方式由用户选择任务的执行计划,然后将各个任务的执行计划添加到数据库中。周期性的从数据库中读取定时任务信息,添加、更新、删除定时任务线程。

当Spring 启动时,就会创建schedulerManager作为总的管理类,由schedulerManager来管理所有的任务,schedulerManager在后台每隔一定的时间(配置)执行一次,来监测数据库中需要创建和更新的定时任务。

schedulerManager读取数据库中的定时任务(任务类、任务方法、执行时间),判断定时触发器中是否存在该任务,如果存在,比较数据库中的任务表达式(cron)是否与当前定时器中的时间一致,如果不一致,更新当前任务时间表达式。如果不存在该任务,将任务加入到定时器中。

此种方式创建任务也是基于MethodInvokingJobDetailFactoryBean,CronTriggerFactoryBean 两个类,但是创建方式为通过代码进行实例化,可以根据实际需要动态的创建,灵活性更加强,使用起来也更加的方便,创建任务有2个步骤,具体如下:

(1)实例化任务

首先实例化MethodInvokingJobDetailFactoryBean,MethodInvokingJobDetailFactoryBean是spring自带的,并将数据库中配置的job相关信息添加到mijdfb,然后调用afterPropertiesSet()方法,这个方法会实例化一个JobDetailImpl,并将相应的信息添加到JobDetailImpl中。该过程实例化了需要定时调度的类和方法,并可以向类和方法中传入制定的参数,使用配置文件的方式无法达到对应的效果。


   
  1. MethodInvokingJobDetailFactoryBean mijdfb= new MethodInvokingJobDetailFactoryBean();
  2. mijdfb.setName(qm.getEnvId());
  3.             mijdfb.setTargetObject(beanFactory.getBean( "service",Mservice.class));
  4.              mijdfb.setTargetMethod( "runTask");
  5.              mijdfb.setConcurrent( false);
  6.             TestEnvDomain [] params =  new TestEnvDomain[ 1];
  7.             params[ 0] = qm;
  8.             mijdfb.setArguments(params);
  9.             mijdfb.afterPropertiesSet();
  10.             org.quartz.JobDetail jd= new JobDetailImpl();
  11.             jd=mijdfb.getObject();
  12.             scheduler.addJob(jd,  true);

(2)实例化触发器

首先实例化CronTriggerFactoryBean,然后添加对应job的时间表表达式等参数信息,然后调用afterPropertiesSet(),这个方法和MethodInvokingJobDetailFactoryBean 中的afterPropertiesSet()类似,最终实例化一个CronTriggerImpl


   
  1. String triggerName=qm.getEnvId() + "Trigger";
  2.             CronTriggerFactoryBean ctb= new CronTriggerFactoryBean();
  3.             ctb.setName(triggerName);
  4.             ctb.setCronExpression(qm.getCronExpression());
  5.             ctb.setJobDetail(jd);
  6.             ctb.afterPropertiesSet();
  7.             CronTrigger cronTrigger= ctb.getObject();
  8.             scheduler.scheduleJob(cronTrigger);
  9.             scheduler.rescheduleJob(cronTrigger.getKey(), cronTrigger);

以上对Scheduled注解方式、配置文件方式,CronTriggerFactoryBean,SimpleTriggerFactoryBean配置文件方式,CronTriggerFactoryBean通过java任务管理器动态创建等不同定时任务配置方法进行了较详细的说明。

通过以上各种配置方式的对比,可以看出,各种配置方式操作都不是特别复杂,相对来说Scheduled配置方式更加的轻量级一些,在一些相对不是很复杂、不涉及线程特别多的场景下可以使用。

Quartz配置方式是一种更加重量级、多线程、分布式等场景下的定时任务配置方式。希望对遇到定时任务配置问题的朋友,可以做一些比较,选择合适的定时任务配置方式。

热 文 推 荐 

为什么 k8s 在阿里能成功?| 问底中国 IT 技术演进

☞微信付费阅读支付宝可用,iOS抽成30%;苹果安卓充电器或统一;UOS 20发布 | 极客头条

如何实现自动化前端开发?

阿里将开源进行到底!

斯坦福博士退学,在 3 个领域改变世界,科技狂人马斯克的巅峰之路

滴滴章文嵩:一个人的20年开源热情和国内互联网开源运动

详谈ARM架构与ARM内核发展史

BSV魔幻爆拉背后:CSW称拿到自证中本聪的关键证据

你点的每个“在看”,我都认真当成了喜欢


转载:https://blog.csdn.net/csdnnews/article/details/104013070
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场