文章提出
在写一个从接口中读取实时数据然后存到自己数据库的小demo时候,发现数据从某一天到现在的都停止了。
先说一下上面读数据存数据的简单逻辑:定时任务从redis中读取上次读取到的时间点timeA,然后从timeA每次加1小时访问接口读取这一小段的代码,然后发现某一小时timeB没数据,把这个时间timeB存到redis中,到下次定时任务的时候在调用。
我的操作就是找到最早没有读到的时间点,然后修改redis中的时间点,启动定时任务就好了。
but 因为间隔的时间比较长,所以任务方法执行的时间超过了定时任务的周期,那么问题来了???
比如我定时任务是每一小时执行一次,我方法执行了1.5个小时。项目从1点启动,1点开始执行定时任务,那么2点的时候任务还没有执行完毕,那么任务是否又开启一个???
代码实操
测试代码1
代码语言:javascript复制@Component
public class TaskComponent {
/**
* 任务周期是2秒
* 任务执行时间是3秒
*/
@Scheduled(cron = "0/2 * * * * ? ")//每2秒执行一次
public void sendMessage() {
System.out.println("定时任务开始执行: " LocalDateTime.now());
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("(业务逻辑)发送消息: " LocalDateTime.now());
} catch (Exception e) {
e.printStackTrace();
}
}
}
代码语言:javascript复制@SpringBootApplication
@EnableScheduling
public class ScheduleDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduleDemoApplication.class, args);
}
}
测试代码2
代码语言:javascript复制@Component
public class TaskComponent {
/**
* 任务周期是2秒
* 任务执行时间是3秒
*/
@Scheduled(cron = "0/2 * * * * ? ")//每2秒执行一次
@Async
public void sendMessage() {
System.out.println("定时任务开始执行: " LocalDateTime.now());
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("(业务逻辑)发送消息: " LocalDateTime.now());
} catch (Exception e) {
e.printStackTrace();
}
}
}
代码语言:javascript复制@SpringBootApplication
@EnableScheduling
@EnableAsync
public class ScheduleDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduleDemoApplication.class, args);
}
}
结论
1)如测试代码1,默认情况下,当定时任务的周期小于方法的执行时间时,定时任务会跳过方法还没有执行完毕的那次(比如我规定1小时执行一次,但是任务的执行时间是1.5小时。当前时间为0点,开始执行定时任务,但是当到1点时候又该执行定时任务了,但是该定时任务还没有执行完,所以跳过。下次执行就是2点的时候了)
2)如测试代码2,如果要实现无论任务是否执行完,都开启新任务的需求,@EnableAsync @Async