10. 定时调度

一、spring task

1. XML配置方式
(1)配置定时器 :<task:scheduler id="scheduler" pool-size="5" />
(2)配置定时任务:
		<task:scheduled-tasks scheduler="scheduler" >		
			<task:scheduled ref="profitScheduler" method="execute" cron="0 0/2 * * * ?"  initial-delay="5000" fixed-delay="3600000" />		
		</task:scheduled-tasks>
2. 注解方式
(1)方法上写注解: @Scheduled(cron = "0 0 3 * * ?") 	
(2)配置文件开启task:<task:annotation-driven/>  (也可以配置定时器)

二、Quartz

1. 基本概念
(1)quartz是一个功能丰富的开源的任务调用系统,它可以创建简单或者复杂的几十、几百、甚至成千上万的job。此外,quartz调度器还支持JTA事务和集群
(2)Quartz是一个完全由java编写的开源作业调度框架,由OpenSymphony组织开源出来。所谓作业调度其实就是按照程序的设定,某一时刻或者时间间隔去执行某个代码	
2. 重要组件
1) Scheduler —— 调度器
a. Scheduler被用来对Trigger和Job进行管理。Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中都拥有自己的唯一的组和名称用来进行彼此的区分,Scheduler可以通过组名或者名称来对Trigger和JobDetail来进行管理
b. 一个Trigger只能对应一个Job,但是一个Job可以对应多个Trigger。每个Scheduler都包含一个SchedulerContext,用来保存Scheduler的上下文。Job和Trigger都可以获取SchedulerContext中的信息
c. Scheduler包含两个重要的组件,JobStore和ThreadPool。JobStore用来存储运行时信息,包括Trigger,Schduler,JobDetail,业务锁等。ThreadPool就是线程池,Quartz有自己的线程池实现。所有任务的都会由线程池执行
2) Trigger —— 触发器
a. Trigger是用来定义Job的执行规则,主要有四种触发器,其中SimpleTrigger和CronTrigger触发器用的最多
	I. SimpleTrigger:从某一个时间开始,以一定的时间间隔来执行任务。它主要有两个属性,repeatInterval  重复的时间间隔;repeatCount 重复的次数,实际上执行的次数是n+1,因为在startTime的时候会执行一次
	II. CronTrigger:适合于复杂的任务,使用cron表达式来定义执行规则 
3) job —— 任务
a. Job是一个任务接口,开发者定义自己的任务须实现该接口实现void execute(JobExecutionContext context)方法,JobExecutionContext中提供了调度上下文的各种信息
b. Job中的任务有可能并发执行,例如任务的执行时间过长,而每次触发的时间间隔太短,则会导致任务会被并发执行。如果是并发执行,就需要一个数据库锁去避免一个数据被多次处理。可以在execute()方法上添加注解@DisallowConcurrentExecution解决这个问题
4) jobDetail —— 任务详情
a. Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job
b. 因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。所以说JobDetail是任务的定义,而Job是任务的执行逻辑
3. 使用步骤
(1)引入jar包: quartz	
(2)配置文件中注册job: <bean name="job1" class="com.quartz.demo.Job1Demo"/>  
(3)注册jobDetail(要引入job以及其方法):
	    <bean id="jobDetail_1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
	        <!-- 执行的类 -->  
	        <property name="targetObject">  
	            <ref bean="job1" />  
	        </property>  
	        <!-- 类中的方法 -->  
	        <property name="targetMethod">  
	            <value>sayHello</value>  
	        </property>  
	    </bean>  
(4)注册触发器(要引入jobDetail以及写好corn表达式):
	    <bean id="cronTrigger_1" class="org.springframework.scheduling.quartz.CronTriggerBean">  
	        <property name="jobDetail">  
	            <ref bean="jobDetail_1" />  
	        </property>  
	        <!-- 每一秒钟执行一次 -->  
	        <property name="cronExpression">  
	            <value>0/1 * * * * ?</value>  
	        </property>  
	    </bean>  
(5)注册调度器(只要把触发器引入就好了,jobDetail已经在触发器里了)	    
	    <!-- 总配置 -->  
	    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
	        <!-- 添加触发器 -->  
	        <property name="triggers">  
	            <list>  
	                <ref bean="cronTrigger_1" />  
	                <ref bean="cronTrigger_2" />  
	            </list>  
	        </property>  
	    </bean>  
4. corn表达式
(1)按顺序依次为
	a. 秒(0~59) 
	b. 分钟(0~59) 
	c. 小时(0~23) 
	d. 天(月)(0~31,但是你需要考虑你月的天数)
	e. 月(0~11) 
	f. 天(星期)(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)
	g. 年份(1970-2099) 
(2)其中每个元素可以是一个值(如6),一个连续区间(9-12),一个间隔时间(8-18/4)(/表示每隔4小时),一个列表(1,3,5),通配符
	a. 0 0/30 9-17 * * ?   朝九晚五工作时间内每半小时
	b. 0 0/5 14,18 * * ?   在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 
(3)由于"月份中的日期"和"星期中的日期"这两个元素互斥的,必须要对其中一个设置?
(4)“/”字符用来指定数值的增量 
	a. 在子表达式(分钟)里的“0/15”表示从第0分钟开始,每15分钟 
	b. 在子表达式(分钟)里的“3/20”表示从第3分钟开始,每20分钟(它和“3,23,43”)的含义一样 
(5)“L” 字符仅被用于天(月)和天(星期)两个子表达式,它是单词“last”的缩写
	a. 在天(月)子表达式中,“L”表示一个月的最后一天
	b. 在天(星期)自表达式中,“L”表示一个星期的最后一天,也就是SAT	
	c. “6L”表示这个月的倒数第6天,“FRIL”表示这个月的最一个星期五 
	d. 在使用“L”参数时,不要指定列表或范围,因为这会导致问题
5. 在项目中用到的实例
1. 直接建了一个web项目,ms_quartz
2. 把定时任务写成了一个json文件,里面有job_name、job_desc(url)、trigger_name、trigger_cron、remark等信息
3. 写了一个监听器,初始化的时候读这个json文件
4. 写个job实现类EshopJob实现Job,且实现execute()方法(里面的逻辑就是读取job_desc,开线程池调其他服务的get请求)
5. 遍历json数组,每次都addJob(String jobName, String jobDesc, String triggerName, Class jobClass, String cron) (传入4的类的.class)
6. 把传进来的配置信息转换为JobDetail(JobBuilder.newJob(jobClass).withIdentity(jobName, JOB_GROUP_NAME).withDescription(jobDesc).build())
7. 然后新建触发器,设定触发器 triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron))
8. 调度容器设置JobDetail和Trigger (sched.scheduleJob(jobDetail, trigger))

参考网址

注:文章是经过参考其他的文章然后自己整理出来的,有可能是小部分参考,也有可能是大部分参考,但绝对不是直接转载,觉得侵权了我会删,我只是把这个用于自己的笔记,顺便整理下知识的同时,能帮到一部分人。
ps : 有错误的还望各位大佬指正,小弟不胜感激

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值