java定时调度任务
- 定时调度:在无人值守的时候后,系统可在某一时刻执行某些特定功能的机制
- 定时调度操作分为两种:定时触发、间隔触发
- java提供两个定时调度处理类:Timer、TimerTask
- TimerTask主要是定义任务执行,相当于启动一个线程执行某些任务的处理
- 企业项目开发过程中基本使用两种定时控制的选择
- quartz组件:企业级定时处理调度组件,需要单独配置
- Spring Task:轻量级组件,配置简单,可以利用Annotation实现配置处理
编写任务程序:
package cn.liang.forget;
import java.text.SimpleDateFormat;
import java.util.TimerTask;
public class TaskDemo01 extends TimerTask {
@Override
public void run() {
System.out.println("【当前日期时间】" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new java.util.Date()));
}
}
编写间隔触发程序:
package cn.liang.test;
import java.util.Timer;
import cn.liang.forget.TaskDemo01;
public class TaskTest01 {
public static void main(String[] args) {
Timer timer = new Timer();
//间隔触发
timer.schedule(new TaskDemo01(),0,1000);
}
}
输出结果:
【当前日期时间】2018-12-04 11:36:03.617
【当前日期时间】2018-12-04 11:36:04.574
【当前日期时间】2018-12-04 11:36:05.578
【当前日期时间】2018-12-04 11:36:06.583
【当前日期时间】2018-12-04 11:36:07.586
【当前日期时间】2018-12-04 11:36:08.587
【当前日期时间】2018-12-04 11:36:09.589
【当前日期时间】2018-12-04 11:36:10.594
......
编写延迟触发程序:
package cn.liang.test;
import java.util.Timer;
import cn.liang.forget.TaskDemo01;
public class TaskTest01 {
public static void main(String[] args) {
Timer timer = new Timer();
//延迟触发
timer.schedule(new TaskDemo01(),2000);
}
}
输出结果:
【当前日期时间】2018-12-04 11:38:58.211
QuartZ实现定时任务
- QuartZ组件的开发过程有两种实现模式
- 要求明确的去继承一个父类
- 利用配置实现方法调度控制,不需要明确继承父类
- 本次直接基于Spring的配置管理的方式来实现定时调度控制
导入QuartZ组件开发包,配置Maven的pom.xml文件
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
继承QuartzJobBean父类实现定时任务
1、定义任务处理类
package cn.liang.forget;
import java.text.SimpleDateFormat;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class TaskDemo2 extends QuartzJobBean{
@Override
protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("【当前日期时间】" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new java.util.Date()));
}
}
2、修改applicationContext.xml配置文件
- 在整个的Spring容器里面注册已经配置好的任务调度类
<!-- 此处表示将要执行的任务控制类在Spring中进行注册,并且告诉容器,谁来执行具体的任务 -->
<bean id="taskFactory1" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!-- 当前可以执行任务的程序类,这个类就是QuartzJobBean的子类 -->
<property name="jobClass" value="cn.liang.forget.TaskDemo2"/>
<!-- 配置一次任务执行时所需要的若干配置信息 -->
<property name="jobDataMap">
<map> <!-- 任务启动之后立即执行 -->
<entry key="timeout" value="0"/>
</map>
</property>
</bean>
<!-- 描述的是间隔触发控制 -->
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<!-- 定义间隔触发的执行程序类 -->
<property name="jobDetail" ref="taskFactory1"/>
<!-- 定义的是是具体的触发的延迟时间,如果设置为0,表示立刻触发 -->
<property name="startDelay" value="0"/>
<!-- 间隔触发的频次,间隔时间单位为“毫秒” -->
<property name="repeatInterval" value="2000"/>
</bean>
<!-- 定义调度工厂类的配置 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="simpleTrigger"/>
</list>
</property>
</bean>
启动Spring容器实现间隔触发任务,所有的间隔触发的控制操作都交由Spring管理
package cn.liang.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TaskTest2 {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
}
}
输出结果:
2018-12-04 14:17:40,050 INFO [org.quartz.impl.StdSchedulerFactory] - Using default implementation for ThreadExecutor
2018-12-04 14:17:40,076 INFO [org.quartz.core.SchedulerSignalerImpl] - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2018-12-04 14:17:40,076 INFO [org.quartz.core.QuartzScheduler] - Quartz Scheduler v.2.3.0 created.
2018-12-04 14:17:40,084 INFO [org.quartz.simpl.RAMJobStore] - RAMJobStore initialized.
2018-12-04 14:17:40,085 INFO [org.quartz.core.QuartzScheduler] - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
2018-12-04 14:17:40,086 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' initialized from an externally provided properties instance.
2018-12-04 14:17:40,086 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler version: 2.3.0
2018-12-04 14:17:40,088 INFO [org.quartz.core.QuartzScheduler] - JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@5bfa9431
2018-12-04 14:17:40,142 INFO [org.springframework.scheduling.quartz.SchedulerFactoryBean] - Starting Quartz Scheduler now
2018-12-04 14:17:40,142 INFO [org.quartz.core.QuartzScheduler] - Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED started.
【当前日期时间】2018-12-04 14:17:40.175
【当前日期时间】2018-12-04 14:17:41.955
【当前日期时间】2018-12-04 14:17:43.956
【当前日期时间】2018-12-04 14:17:45.956
【当前日期时间】2018-12-04 14:17:47.956
......
QuartZ使用Cron实现定时触发
- QuartZ最大的优势是可以结合cron表达式实现定时触发
- cron服务器可以根据配置文件在约定的时间来执行特定的任务
cron表达式是一个字符串
- seconds minutes hours day month week year
- seconds:表示秒,可以是从0到59之间的任何整数。
- minutes: 表示分钟,可以是从0到59之间的任何整数。
- hours:表示小时,可以是从0到23之间的任何整数。
- day:表示日期,可以是从1到31之间的任何整数。
- month:表示月份,可以是从1到12之间的任何整数或JAN-DEC范围。
- week:表示星期几,可以是从1到7之间的任何整数或SUN-SAT范围,这里的1代表星期日。
- year:表示年,有效范围为1970-2099年
cron表达式作用域的含义
- * :表示匹配该域的任意值,假如在minutes域使用*则表示每分钟都会触发事件
- ? :只能用在day和week两个域上
- - :表示范围,如果在minutes域使用5-20则表示从5分到20分内,每分钟触发一次
- / :表示起始时间开始触发,然后每隔固定时间触发一次
- , :表示列出枚举值
- L :表示最后,只能用在day和week两个域上,如在week域使用5L则表示最后一个星期四触发
- W :表示有效工作日(周一到周五),只能出现day域
- # :表示确认每个月的第几个星期几,只能出现day域,如4#2表示某月的第二个星期三
cron表达式举例
- 0 0 2 1 * ? * :表示在每月的1日的凌晨2点调度任务
- 0 15 10 ? * MON-FRI :表示周一到周五每天上午10:15执行作业
- 0 15 10 ? * 6L 2018-2030 :表示2018-2030年的每个月的最后一个星期五上午10:15执行作业
- 0 0 10,14,16 * * ? :表示每天上午10点,下午2点、4点
- 0 0/30 9-17 * * ? :表示9点到17点工作时间内每半小时
- 0 0 12 ? * WED :表示每个星期三中午12点
- 0 0 12 * * ? :表示每天中午12点触发
- 0 15 10 ? * * :表示每天10:15触发
- 0 15 10 * * ? :表示每天10:15触发
- 0 15 10 * * ? 2005 :表示2005年的每天10:15触发
- 0 * 14 * * ? :表示每天14点到14:59分期间,每1分钟触发
- 0 0/5 14 * * ? :表示每天14点到14:55分期间,每5分钟触发
- 0 0/5 14,18 * * ? :表示每天14点到14:55分和18点到18:55分期间,每5分钟触发
- 0 0-5 14 * * ? :表示每天14点到14:05分期间,每1分钟触发
- 0 10,44 14 ? 3 WED :表示每年三月的星期三的14:10和14:44触发
- 0 15 10 ? * MON-FRI :表示周一到周五的10:15触发
修改applicationContext.xml配置文件,使用间隔控制类进行定时触发处理
<bean id="taskFactory1" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="cn.liang.forget.TaskDemo2"/>
<property name="jobDataMap">
<map>
<entry key="timeout" value="0"/>
</map>
</property>
</bean>
<!-- 使用定时触发处理 -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- 定义间隔触发的执行程序类 -->
<property name="jobDetail" ref="taskFactory1"/>
<!-- 定义CRON表达式,描述的是每分钟触发一次 -->
<property name="cronExpression" value="0 * * * * ?"/>
</bean>
<!-- 定义调度工厂类的配置 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
</bean>
启动Spring容器实现间隔触发任务,所有的间隔触发的控制操作都交由Spring管理
package cn.liang.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TaskTest2 {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
}
}
输出结果:
2018-12-04 15:13:07,113 INFO [org.quartz.impl.StdSchedulerFactory] - Using default implementation for ThreadExecutor
2018-12-04 15:13:07,129 INFO [org.quartz.core.SchedulerSignalerImpl] - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2018-12-04 15:13:07,129 INFO [org.quartz.core.QuartzScheduler] - Quartz Scheduler v.2.3.0 created.
2018-12-04 15:13:07,130 INFO [org.quartz.simpl.RAMJobStore] - RAMJobStore initialized.
2018-12-04 15:13:07,131 INFO [org.quartz.core.QuartzScheduler] - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
2018-12-04 15:13:07,131 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' initialized from an externally provided properties instance.
2018-12-04 15:13:07,131 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler version: 2.3.0
2018-12-04 15:13:07,132 INFO [org.quartz.core.QuartzScheduler] - JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@5bfa9431
2018-12-04 15:13:07,152 INFO [org.springframework.scheduling.quartz.SchedulerFactoryBean] - Starting Quartz Scheduler now
2018-12-04 15:13:07,153 INFO [org.quartz.core.QuartzScheduler] - Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED started.
【当前日期时间】2018-12-04 15:14:00.021
【当前日期时间】2018-12-04 15:15:00.004
QuartZ通过配置自动实现调度
- 由于QuartZ的调用需要继承QuartzJobBean父类,容易导致单继承的局限控制
- 因此Spring提供了不继承任何类实现的定时处理操作任务
定义一个处理任务的执行类
package cn.liang.forget;
import java.text.SimpleDateFormat;
public class TaskDemo3{
public void task(){
System.out.println("【当前日期时间】" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new java.util.Date()));
}
}
修改applicationContext.xml配置文件
<!-- 配置自定义的任务执行类操作 -->
<bean id="taskFactory2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- 定义要执行任务调度的任务类对象,需要一个具体的对象处理 -->
<property name="targetObject">
<bean class="cn.liang.forget.TaskDemo3"/>
</property>
<!-- 定义任务执行的时候所调用的操作方法名称 -->
<property name="targetMethod" value="task"/>
</bean>
<!-- 使用定时触发处理 -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- 定义间隔触发的执行程序类 -->
<property name="jobDetail" ref="taskFactory2"/>
<!-- 定义CRON表达式,描述的是每分钟触发一次 -->
<property name="cronExpression" value="0 * * * * ?"/>
</bean>
<!-- 定义调度工厂类的配置 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
</bean>
启动Spring容器实现间隔触发任务,所有的间隔触发的控制操作都交由Spring管理
package cn.liang.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TaskTest2 {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
}
}
输出结果:
2018-12-04 15:35:59,257 INFO [org.quartz.impl.StdSchedulerFactory] - Using default implementation for ThreadExecutor
2018-12-04 15:35:59,269 INFO [org.quartz.core.SchedulerSignalerImpl] - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2018-12-04 15:35:59,270 INFO [org.quartz.core.QuartzScheduler] - Quartz Scheduler v.2.3.0 created.
2018-12-04 15:35:59,270 INFO [org.quartz.simpl.RAMJobStore] - RAMJobStore initialized.
2018-12-04 15:35:59,271 INFO [org.quartz.core.QuartzScheduler] - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
2018-12-04 15:35:59,271 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' initialized from an externally provided properties instance.
2018-12-04 15:35:59,271 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler version: 2.3.0
2018-12-04 15:35:59,272 INFO [org.quartz.core.QuartzScheduler] - JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@7995092a
2018-12-04 15:35:59,306 INFO [org.springframework.scheduling.quartz.SchedulerFactoryBean] - Starting Quartz Scheduler now
2018-12-04 15:35:59,306 INFO [org.quartz.core.QuartzScheduler] - Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED started.
【当前日期时间】2018-12-04 15:36:00.024
【当前日期时间】2018-12-04 15:37:00.005
【当前日期时间】2018-12-04 15:38:00.003