Spring3.0后提供Spring Task实现任务调度,支持按日历调度,相比Quartz功能稍简单,但是在开发基本够用,支持注解编程方式。我们这里是在SpringBoot下应用SpringTask。
1、SpirngTask入门
【入门案例】
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @ClassName YwTask
* @描述 spring task的配置类
* @Date
**/
@Component
@EnableScheduling //表示开启SpringTask
public class YwTask {
private static final Logger LOGGER = LoggerFactory.getLogger(YwTask.class);
// @Scheduled(fixedRate = 5000) //上次执行开始时间后5秒执行
// @Scheduled(fixedDelay = 5000) //上次执行完毕后5秒执行
// @Scheduled(initialDelay=3000, fixedRate=5000) //第一次延迟3秒,以后每隔5秒执行一次
@Scheduled(cron="0/3 * * * * *")//每隔3秒执行一次
public void task1(){
LOGGER.info("===============测试定时任务1开始===============");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.info("===============测试定时任务1结束===============");
}
}
【注意】(1)在该类上使用了@Component和@EnableScheduling;其中@EnableScheduling表示开启SpringTask,如果不在配置类上添加@EnableScheduling注解,则需要在启动类上使用此注解。
(2)@Scheduled注解表示Task按照什么方式执行。
2、Cron表达式
Cron表达式包括6部分:秒(0~59) 分钟(0~59) 小时(0~23) 月中的天(1~31) 月(1~12) 周中的天。(填写MON,TUE,WED,THU,FRI,SAT,SUN,或数字1~7 1表示MON,依次类推)
特殊字符介绍:
(1)"/"字符表示指定数值的增量;
(2)"*"字符表示所有可能的值;
(3)"-"字符表示区间范围;
(4)"," 字符表示列举;
(5)"?"字符仅被用于月中的天和周中的天两个子表达式,表示不指定值;
3、SpringTask中的注解
3.1、@EnableScheduling注解
@EnableScheduling注解表示开启SpringTask,一般放在配置类上或者是SpringBoot的启动类上。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({SchedulingConfiguration.class})
@Documented
public @interface EnableScheduling {
}
3.2、@Scheduled注解
【@Scheduled注解源码】
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
//cron属性表示使用cron表达式
String cron() default "";
String zone() default "";
//fixedDelay表示以固定速率执行,单位是毫秒;上次执行完毕后多少毫秒执行
long fixedDelay() default -1L;
String fixedDelayString() default "";
//fixedRate表示以固定速率执行,单位是毫秒;上次执行时间开始后多少毫秒执行。
long fixedRate() default -1L;
String fixedRateString() default "";
long initialDelay() default -1L;
String initialDelayString() default "";
}
通过源码我们需要注意试fixedRate和fixedDelay这两个属性的区别和应用。
4、SpringTask串行执行
在Spring框架下SpringTask默认是按照串行执行的。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@EnableScheduling //表示开启SpringTask
public class YwTask {
@Scheduled(cron="0/3 * * * * *")//每隔3秒执行一次
public void task1(){
LOGGER.info("===============测试定时任务1开始===============");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.info("===============测试定时任务1结束===============");
}
@Scheduled(fixedRate = 3000) //上次执行开始时间后5秒执行
public void task2(){
LOGGER.error("===============测试定时任务2开始===============");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.error("===============测试定时任务2结束===============");
}
}
通过上面的代码运行,我们发现只有当任务1执行完成之后,任务2才开始执行。
5、SpringTask并行执行
在实际的项目应用中,通常是有多个任务,且这些任务都是不相干的。这时就需要并行执行任务。如果想实现SpringTask执行并行任务,我们需要创建异步任务类实现SchedulingConfigurer和 AsyncConfigurer这两个接口,并且实现configureTasks()方法。
/**
* @ClassName AsyncTaskConfig
* @描述 创建异步任务配置类
* 需要配置线程池实现多线程调度任务
**/
@Component
@EnableScheduling
public class AsyncTaskConfig implements SchedulingConfigurer, AsyncConfigurer {
//线程池线程数量
private int corePoolSize = 10;
@Bean
public ThreadPoolTaskScheduler taskScheduler()
{
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.initialize();//初始化线程池
scheduler.setPoolSize(corePoolSize);//线程池容量
return scheduler;
}
@Override
public Executor getAsyncExecutor() {
Executor executor = taskScheduler();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.setTaskScheduler(taskScheduler());
}
}
我们再次运行时,就会发现第四步中的代码会按照并行的方式运行。