Java Spring中的调度:@Schedule和@EnableScheduling导致方法的多次调用
我有一个服务,它必须运行一个作业才能从另一个服务获取和刷新数据。作业必须在启动时运行,并且每隔几个小时/天运行一次。我正在研究计划作业的行为,根据日志,它似乎被连续调用了两次(见下文) 这里还有每5分钟调用一次刷新方法的日志,可以看出,它被调用了两次:Java Spring中的调度:@Schedule和@EnableScheduling导致方法的多次调用,java,spring,spring-boot,spring-scheduled,Java,Spring,Spring Boot,Spring Scheduled,我有一个服务,它必须运行一个作业才能从另一个服务获取和刷新数据。作业必须在启动时运行,并且每隔几个小时/天运行一次。我正在研究计划作业的行为,根据日志,它似乎被连续调用了两次(见下文) 这里还有每5分钟调用一次刷新方法的日志,可以看出,它被调用了两次: 2020-07-02 17:30:00.006 INFO 30416 --- [ scheduling-1] c.d.p.d.service.ServiceImpl : org.springframework.boot.web.servl
2020-07-02 17:30:00.006 INFO 30416 --- [ scheduling-1] c.d.p.d.service.ServiceImpl : org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6db9cae5
2020-07-02 17:30:00.006 INFO 30416 --- [ scheduling-1] c.d.p.d.serice.ServiceImpl : This object: 357813323
2020-07-02 17:30:00.006 INFO 30416 --- [ scheduling-1] c.d.p.d.service.ServiceImpl : Times called: 1
....
2020-07-02 17:30:32.001 INFO 30416 --- [ scheduling-1] c.d.p.d.service.ServiceImpl : org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6db9cae5
2020-07-02 17:30:32.001 INFO 30416 --- [ scheduling-1] c.d.p.d.service.ServiceImpl : This object: 357813323
2020-07-02 17:30:32.001 INFO 30416 --- [ scheduling-1] c.d.p.d.service.ServiceImpl : Times called: 2
我没有web.xml,只使用默认值。我在根级别使用了@EnableScheduling标记:
@EnableScheduling
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
我研究了类似的问题,但找不到任何可以帮助我找到这个bug来源的东西。感谢您的帮助:)您所描述的行为是正常的和有意的 正如您所写,您的cron表达式是
***/5****
,这意味着,根据,它将每隔5分钟运行一秒:
一个类似cron的表达式,扩展了通常的UN*X定义,以包括秒、分钟、小时、月日、月日和星期日的触发器
例如,{@code“0****MON-FRI”}表示在工作日每分钟一次(在一分钟的顶端-第0秒)。
从左到右读取的字段解释如下
- 第二
- 分钟
- 时辰
- 月日
- 月
- 星期几
@Scheduled(cron = "* */5 * * * *")
private void refresh() {
log.info("Times called: " + timesCalled);
timesCalled++;
}
并观察其行为:
14:20:13.001 INFO 8980 --- [ sch-1] com.example.demo.Sched : Times called: 13
14:20:14.001 INFO 8980 --- [ sch-1] com.example.demo.Sched : Times called: 14
14:20:15.003 INFO 8980 --- [ sch-1] com.example.demo.Sched : Times called: 15
14:20:59.002 INFO 8980 --- [ sch-1] com.example.demo.Sched : Times called: 59
14:25:00.000 INFO 8980 --- [ sch-1] com.example.demo.Sched : Times called: 60
14:25:01.000 INFO 8980 --- [ sch-1] com.example.demo.Sched : Times called: 61
14:25:02.001 INFO 8980 --- [ sch-1] com.example.demo.Sched : Times called: 62
14:25:03.002 INFO 8980 --- [ sch-1] com.example.demo.Sched : Times called: 63
正如你所见,它每秒钟运行一次,直到每分钟结束。然后等到14点25分,每一秒都要跑
但为什么它在问题案例中只运行了2次?
这很简单:data=fetchService.getAndUpdate()代码>大约需要30秒,因为您只有一个线程用于调度,所以它必须等待最后一次迭代完成,直到可以重新开始
解决方案
要解决此问题,只需将第一个通配符替换为0
:
0 */5 * * * *
并且您的作业将每5分钟运行一次。刷新的值是多少。计划
?也许你想看看这是一个正常的cron作业格式:*/5****我将这个问题标记为离题,因为这种行为是由cron表达式中的一个简单输入错误引起的,因此未来的读者对此不感兴趣。根据需要更改cron值
0 */5 * * * *