首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring中的调度:@ Scheduling和@EnableScheduling导致多个方法调用

Spring中的调度:@ Scheduling和@EnableScheduling导致多个方法调用
EN

Stack Overflow用户
提问于 2020-07-02 16:08:25
回答 1查看 779关注 0票数 1

我有一个服务,它必须运行一个作业才能从另一个服务获得和刷新它的数据。这项工作必须在启动时运行,每隔几个小时/天一次。我正在查看计划作业的行为,根据日志,它似乎被连续调用了两次(参见下面)。

代码语言:javascript
复制
@Service
public class ServiceImpl implements ServiceInterface {

@Autowired
private FetchService fetchService;

private int timesCalled = 0;
private Data data;

@PostConstruct
private void initialize() {
    data = fetchService.getAndUpdate();
}

@Scheduled(cron = "* */5 * * * *")
private void refresh() {
    LOG.info(appContext.getId());
    LOG.info("This object: " + System.identityHashCode(this));
    LOG.info("Times called: " +  timesCalled);
    timesCalled++;
    data = fetchService.getAndUpdate();
}
...

这里还有每5分钟调用一次刷新方法的日志,可以看到它被调用了两次:

代码语言:javascript
复制
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标记:

代码语言:javascript
复制
@EnableScheduling
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

我调查了类似的问题,但找不到任何可以帮助我找到这个bug的来源的东西。如有任何帮助,我们将不胜感激:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-03 12:26:41

你所描述的行为是正常的和有意的。

正如您所写的,cron表达式是* */5 * * * *,这意味着,根据春季指南,它每5分钟运行一次:

一个类似cron的表达式,扩展了通常的UN*X定义,在第二、分钟、小时、月、月和周的日期包括触发器。 例如,{@code "0 ***MON“}是指平日每分钟一次(在分钟的顶部-第0秒)。从左到右读取的字段解释如下。

  • 第二
  • 分分钟
  • 小时
  • 月中的一天
  • 月份
  • 一周中的一天

可以很容易地通过获取代码和cron表达式来复制:

代码语言:javascript
复制
@Scheduled(cron = "* */5 * * * *")
private void refresh() {
    log.info("Times called: " +  timesCalled);
    timesCalled++;
}

并观察其行为:

代码语言:javascript
复制
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,每一秒再跑一次。

但是为什么它在问题案例中只运行两次呢?

这很简单:data = fetchService.getAndUpdate();大约需要30秒,而且因为您的调度只有一个线程,所以它必须等到最后一个迭代完成,直到它可以重新开始。

解决方案

要解决这个问题,只需将第一个通配符替换为0

代码语言:javascript
复制
0 */5 * * * *

你的工作每5分钟就能完成一次。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62700643

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档