@EnableScheduling
@Scheduled有三种配置方式
- cron
- fixedRate
- fixedDelay
cron是固定时间进行处理
fixedRate任务执行间隔是两次任务是开始点,如果执行时长超过间隔,那么会在任务执行结束后立刻执行下一次,除非用@Async注解了
fixedDelay任务执行间隔是前次任务结束和下次任务开始点
这篇文章主要探讨的是如果任务执行时间超过了定时任务间隔时间,定时任务会如何执行。
cron
@EnableScheduling
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
@Scheduled(cron = "*/5 * * * * *")
public String ssss(){
System.out.println(new Date(System.currentTimeMillis()));
try {
Thread.sleep(7000);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
Mon Sep 09 12:51:30 CST 2019
Mon Sep 09 12:51:40 CST 2019
Mon Sep 09 12:51:50 CST 2019
Mon Sep 09 12:52:00 CST 2019
Mon Sep 09 12:52:10 CST 2019
cron都是按照整点来运行的,比如5秒一次,他会在0,5,10…秒运行,如果那个时间点还没运行结束,那么就会跳过这次任务。
fixedRate
//省略部分代码
@Scheduled(fixedRate = 5000)
public String ssss(){
System.out.println(new Date(System.currentTimeMillis()));
try {
Thread.sleep(7000);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
Mon Sep 09 12:58:27 CST 2019
Mon Sep 09 12:58:34 CST 2019
Mon Sep 09 12:58:41 CST 2019
Mon Sep 09 12:58:48 CST 2019
Mon Sep 09 12:58:55 CST 2019
Mon Sep 09 12:59:02 CST 2019
可以看出,fixedRate会在执行结束后立刻就执行下一次任务,实际上可以理解为,fixedRate预先设置了一个任务执行表,当一个任务执行结束后会根据执行表中下一个任务的执行时间来判断是否达到时机执行
private AtomicBoolean flag = new AtomicBoolean(true);
@Scheduled(fixedRate = 5000)
public String ssss(){
System.out.println(new Date(System.currentTimeMillis()));
if(flag.getAndSet(false)){
try {
Thread.sleep(13000);
}catch (Exception e){
e.printStackTrace();
}
}
return null;
}
Mon Sep 09 13:03:00 CST 2019
Mon Sep 09 13:03:13 CST 2019
Mon Sep 09 13:03:13 CST 2019
Mon Sep 09 13:03:15 CST 2019
Mon Sep 09 13:03:20 CST 2019
Mon Sep 09 13:03:25 CST 2019
第一次执行延迟了8秒钟,那么下面几次都会立刻执行,直到把这延迟的8秒钟追回来
Async
使用@Async可以避免这个问题,但是要记得先设置ThreadPoolTaskScheduler的线程数,否则默认为1,就算开启了异步也只有一个线程在运行。
@EnableAsync
@EnableScheduling
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
@Bean
public TaskScheduler taskScheduler(){
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(5);
return taskScheduler;
}
private AtomicBoolean flag = new AtomicBoolean(true);
@Scheduled(fixedRate = 5000)
@Async
public void ssss(){
System.out.println(new Date(System.currentTimeMillis()));
try {
Thread.sleep(7000);
}catch (Exception e){
e.printStackTrace();
}
}
}
Mon Sep 09 14:01:15 CST 2019
Mon Sep 09 14:01:20 CST 2019
Mon Sep 09 14:01:25 CST 2019
Mon Sep 09 14:01:30 CST 2019
Mon Sep 09 14:01:35 CST 2019
Mon Sep 09 14:01:40 CST 2019
Mon Sep 09 14:01:45 CST 2019
cron也同理
@Asycn需要三步配置,否则没有效果
- 在@SpringBootApplication启动类 添加注解@EnableAsync
- 异步方法使用注解@Async ,返回值为void或者Future
- 切记一点 ,异步方法和调用方法一定要**** 写在不同的类中 ****,如果写在一个类中,
是没有效果的
@Async具体解释和实现代码可以参考另一个博主的文章
https://blog.csdn.net/clementad/article/details/53607311