项目是spring boot 2.0,默认集成了Scheduler,只需要以下两步直接就能使用:
一.在启动类上加上@EnableScheduling,开启Scheduler定时任务。
二.在需要定时运行的方法上加上@Scheduled()注解,括号里面是定时的规则:
@Component
public class Scheduler {
@Scheduled(cron = "0/1 * * * * ? ")
public void test() {
System.out.println("定时任务" + new Date());
}
}
像上面这段代码,我用的是cron表达式去定义定时规则,表示每一秒执行一次,效果如下:
当然,@Scheduled注解还有其他的参数可以使用,我们先看看它具体有哪些参数:
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
String CRON_DISABLED = "-";
//这个字段代表时区,接收一个java.util.TimeZone#ID,而cron表达式会基于该时区解析,默认情况下,它是空字符串,取的是服务器所在地的时区,这个字段溜空就好。
String zone() default "";
long fixedDelay() default -1;
String fixedDelayString() default "";
long fixedRate() default -1;
String fixedRateString() default "";
long initialDelay() default -1;
String initialDelayString() default "";
}
zone:这个字段代表时区,接收一个java.util.TimeZone#ID,而cron表达式会基于该时区解析,默认情况下,它是空字符串,取的是服务器所在地的时区,这个字段留空就好。
fixedDelay:上一次事件执行完的时间点后,过多久执行下一次
@Scheduled(fixedDelay = 5000)//上一次事件执行完后,过5s执行下一次
效果如下:
fixedDelayString:和fixedDelay一样的效果,表示上一次事件执行完后,过多久执行下一次,不过它是字符串形式,支持占位符,所以可以通过${ }这种形式去配置文件里取值。
time:
limit: 5000
@Scheduled(fixedDelayString = "${time.limit}")//上一次事件执行完后,过5s执行下一次
效果如下:
fixedRate:上次开始执行事件的时间点后,多久执行下一个
改造一下测试方法,让线程睡眠2s钟:
@Component
public class Scheduler {
@Scheduled(fixedRate = 5000)//上次开始执行事件的时间点后,多久执行下一个
public void test() throws Exception {
Thread.sleep(2000);
System.out.println("定时任务" + new Date());
}
}
效果如下:
会发现两次事件的时间间隔还是5s,并没有因为线程睡眠了两秒钟后变成7s。
fixedRateString:和fixedRate一样的效果,表示上次开始执行事件的时间点后,多久执行下一个,不过它也是字符串形式,支持占位符,所以可以通过${ }这种形式去配置文件里取值。
@Scheduled(fixedRateString = "${time.limit}")//上次开始执行事件的时间点后,多久执行下一个
效果如下:
initialDelay:第一次事件执行,延长多少时间开始
@Scheduled(initialDelay = 5000, fixedRate = 5000)//项目启动后,当前时间过5秒后开始执行事件,同时事件开始执行时间点后,每隔5s调用一次事件
效果如下:
initialDelayString:和initialDelay一样的效果,表示第一次事件执行,延长多少时间开始,不过它也是字符串形式,支持占位符,所以可以通过${ }这种形式去配置文件里取值。
@Scheduled(initialDelayString = "${time.limit}", fixedRate = 5000)//项目启动后,当前时间过5秒后开始执行事件,同时事件开始执行时间点后,每隔5s调用一次事件
效果如下:
以上就是几个参数的作用
不过项目中我们一般都是用cron表达式做定时的,至于怎么自己写cron表达式,我也没去研究,也不准备get这技能,以下是一个cron表达式生成器网站,要什么效果的他都能做到,比自己写的靠谱多了。。。
异步调用定时任务
测试代码如下,有两个定时任务:
@Component
public class Scheduler {
@Scheduled(fixedDelay = 5000)
public void test() throws Exception {
Thread.sleep(2000);
System.out.println("定时任务一执行的时间是" + new Date());
}
@Scheduled(fixedDelay = 1000)
public void test1() throws Exception {
Thread.sleep(2000);
System.out.println("定时任务二执行的时间是" + new Date());
}
}
没有引入异步,效果如下:
可以看到从14:55:48开始是执行任务二,任务执行完1s,加上线程睡眠2s,所以过了3s钟,到了14:55:51再次执行任务二,线程继续睡眠2s,合计刚好5s,所以在14:55:53执行任务一,任务一线程同样睡眠两秒,所以到了14:55:55才执行任务二。可以看出,任务二在等待任务一执行完成才执行,不然的话,任务二在执行完事件1s后就应该在14:55:54继续执行。
引入异步:
- 在启动类加上@EnableAsync开启异步功能:
- 在需要异步执行的方法上加上@Async注解
@Component
public class Scheduler {
@Scheduled(fixedDelay = 5000)
@Async
public void test() throws Exception {
Thread.sleep(2000);
System.out.println("定时任务一执行的时间是" + new Date());
}
@Scheduled(fixedDelay = 1000)
@Async
public void test1() throws Exception {
Thread.sleep(2000);
System.out.println("定时任务二执行的时间是" + new Date());
}
}
执行后效果如下:
可以很直观的看到,任务二没有再等待任务一了,两者是并行执行的,互不影响。