我有一个服务,它必须运行一个作业才能从另一个服务获得和刷新它的数据。这项工作必须在启动时运行,每隔几个小时/天一次。我正在查看计划作业的行为,根据日志,它似乎被连续调用了两次(参见下面)。
@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分钟调用一次刷新方法的日志,可以看到它被调用了两次:
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的来源的东西。如有任何帮助,我们将不胜感激:)
发布于 2020-07-03 12:26:41
你所描述的行为是正常的和有意的。
正如您所写的,cron表达式是* */5 * * * *,这意味着,根据春季指南,它每5分钟运行一次:
一个类似cron的表达式,扩展了通常的UN*X定义,在第二、分钟、小时、月、月和周的日期包括触发器。 例如,{@code "0 ***MON“}是指平日每分钟一次(在分钟的顶部-第0秒)。从左到右读取的字段解释如下。
可以很容易地通过获取代码和cron表达式来复制:
@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,每一秒再跑一次。
但是为什么它在问题案例中只运行两次呢?
这很简单:data = fetchService.getAndUpdate();大约需要30秒,而且因为您的调度只有一个线程,所以它必须等到最后一个迭代完成,直到它可以重新开始。
解决方案
要解决这个问题,只需将第一个通配符替换为0。
0 */5 * * * *你的工作每5分钟就能完成一次。
https://stackoverflow.com/questions/62700643
复制相似问题