Spring @scheduled注解周期性执行超时任务对任务调度的影响分析

本文测试了@scheduled注解中参数cron,fixedDelay,fixedRate参数周期性调度任务时,任务执行时长不同对任务调度的影响情况,包含作业任务执行时长小于任务执行周期,作业任务执行时长与任务执行频率同频,作业任务执行时长大于任务执行周期的三种情况,用于对实际业务设置定时执行作为参考。

第一种.cron参数周期性执行不同时长业务分析

情况1:调度周期大于任务执行时长情况

模拟定时周期为3秒执行一次,任务执行耗时1秒,执行结果如图所示:第一次作业开始时间为16:25:36,结束时间为16:25:37,第二次作业开始时间为:16:25:39,结束时间为16:25:40,第三次作业开始时间为16:25:43。由执行结果可知:作业调度依次间隔为3秒钟时间执行一次,符合预期。

	/**
     *  任务周期3S 模拟作业执行时长 1S
     */
    @Scheduled(cron = "0/3 * * * * ?")
    public void testJobCron() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(1000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }

Spring @scheduled注解周期性执行超时任务对任务调度的影响分析_第1张图片

情况2:调度周期与任务执行时长相同的情况

模拟定时周期为3秒执行一次,任务执行耗时3秒,执行结果如图所示:第一次作业开始时间为16:31:48,结束时间为16:31:51,第二次作业开始时间为:16:31:54,结束时间为16:31:57,第三次作业开始时间为16:32:00。由执行结果可知:作业调度间隔已经不是3秒钟时间执行一次(作业完后3秒执行下一次调度),不符合预期。

	/**
     *  任务周期3S 模拟作业执行时长 3S
     */
    @Scheduled(cron = "0/3 * * * * ?")
    public void testJobCron() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(3000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }

Spring @scheduled注解周期性执行超时任务对任务调度的影响分析_第2张图片

情况3:调度周期小于任务执行时长的情况

模拟定时周期为3秒执行一次,任务执行耗时5秒,执行结果如图所示:第一次作业开始时间为16:33:24,结束时间为16:33:29,第二次作业开始时间为:16:33:30,结束时间为16:33:35,第三次作业开始时间为16:33:36。由执行结果可知:任务调度间隔不为3秒钟时间执行一次(作业完后隔1秒钟执行下一次调度),不符合预期。

    /**
     *  任务周期3S 模拟作业执行时长 5S
     */
    @Scheduled(cron = "0/3 * * * * ?")
    public void testJobCron() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(5000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }

Spring @scheduled注解周期性执行超时任务对任务调度的影响分析_第3张图片

第二种.fixedRate参数周期性执行不同时长业务分析

情况1:调度周期大于任务执行时长情况

模拟定时周期为3秒执行一次,任务执行耗时1秒,执行结果如图所示:第一次作业开始时间为16:35:45,结束时间为16:35:46,第二次作业开始时间为:16:35:48,结束时间为16:35:49,第三次作业开始时间为16:35:51。由执行结果可知:作业调度依次间隔为3秒钟时间执行一次,符合预期。

	/**
     * 3S执行一次 模拟作业执行时长1S
     * 上一次开始执行时间点之后多长时间再执行
     */
    @Scheduled(fixedRate = 3000L)
    public void testJobFixedRate() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(1000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }

Spring @scheduled注解周期性执行超时任务对任务调度的影响分析_第4张图片

情况2:调度周期与任务执行时长相同的情况

模拟定时周期为3秒执行一次,任务执行耗时3秒,执行结果如图所示:第一次作业开始时间为16:37:20,结束时间为16:37:23,第二次作业开始时间为:16:37:23,结束时间为16:37:26,第三次作业开始时间为16:37:26。由执行结果可知:作业调度间隔3秒钟时间执行一次(作业完后立即执行下一次调度),符合预期。

	/**
     * 3S执行一次 模拟作业执行时长3S
     * 上一次开始执行时间点之后多长时间再执行
     */
    @Scheduled(fixedRate = 3000L)
    public void testJobFixedRate() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(3000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }

Spring @scheduled注解周期性执行超时任务对任务调度的影响分析_第5张图片

情况3:调度周期小于任务执行时长的情况

模拟定时周期为3秒执行一次,任务执行耗时5秒,执行结果如图所示:第一次作业开始时间为16:39:52,结束时间为16:39:57,第二次作业开始时间为:16:39:57,结束时间为16:40:02,第三次作业开始时间为16:40:02。由执行结果可知:任务调度间隔不为3秒钟时间执行一次(作业完后立即执行下一次调度,调度间隔由任务执行时长决定),不符合预期。

	/**
     * 3S执行一次 模拟作业执行时长5S
     * 上一次开始执行时间点之后多长时间再执行
     */
    @Scheduled(fixedRate = 3000L)
    public void testJobFixedRate() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(5000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }

Spring @scheduled注解周期性执行超时任务对任务调度的影响分析_第6张图片

第三种.fixedDelay参数周期性执行不同时长业务分析

情况1:调度周期大于任务执行时长情况

模拟定时周期为3秒执行一次,任务执行耗时1秒,执行结果如图所示:第一次作业开始时间为16:42:32,结束时间为16:42:33,第二次作业开始时间为:16:42:36,结束时间为16:42:37,第三次作业开始时间为16:42:40。由执行结果可知:作业调度依次为执行结束后间隔3秒钟时间执行下一次任务,符合预期。

	/**
     * 3S执行一次 模拟作业执行时长1S
     * 上一次执行完毕时间点之后多长时间再执行
     */
    @Scheduled(fixedDelay = 3000L)
    public void testJobFixedDelay() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(1000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }

Spring @scheduled注解周期性执行超时任务对任务调度的影响分析_第7张图片

情况2:调度周期与任务执行时长相同的情况

模拟定时周期为3秒执行一次,任务执行耗时3秒,执行结果如图所示:第一次作业开始时间为16:44:11,结束时间为16:44:14,第二次作业开始时间为:16:44:17,结束时间为16:44:20,第三次作业开始时间为16:44:23。由执行结果可知:作业调度依次为执行结束后间隔3秒钟时间执行下一次任务,符合预期。

	/**
     * 3S执行一次 模拟作业执行时长3S
     * 上一次执行完毕时间点之后多长时间再执行
     */
    @Scheduled(fixedDelay = 3000L)
    public void testJobFixedDelay() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(3000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }

Spring @scheduled注解周期性执行超时任务对任务调度的影响分析_第8张图片

情况3:调度周期小于任务执行时长的情况

模拟定时周期为3秒执行一次,任务执行耗时5秒,执行结果如图所示:第一次作业开始时间为16:45:57,结束时间为16:46:02,第二次作业开始时间为:16:46:05,结束时间为16:46:10,第三次作业开始时间为16:46:13。由执行结果可知:作业调度依次为执行结束后间隔3秒钟时间执行下一次任务,符合预期。

	/**
     * 3S执行一次 模拟作业执行时长5S
     * 上一次执行完毕时间点之后多长时间再执行
     */
    @Scheduled(fixedDelay = 3000L)
    public void testJobFixedDelay() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(5000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }

Spring @scheduled注解周期性执行超时任务对任务调度的影响分析_第9张图片

@scheduled注解参数简介

1.cron

支持cron表达式方式进行作业调度。

2.zone

将解析 cron 表达式的时区。默认情况下,此属性是空字符串(即将使用服务器的本地时区)。

3.fixedDelay

上一次执行完毕时间点之后多长时间再执行。

4.fixedDelayString

意思fixedDelay相同,只是使用字符串的形式。支持配置文件中配置参数,采用占位符获取配置参数的情形。

5.fixedRate

上一次开始执行时间点之后多长时间再执行。

6.fixedRateString

意思fixedRate相同,只是使用字符串的形式。支持配置文件中配置参数,采用占位符获取配置参数的情形。

7.initialDelay

配合fixedDelay与fixedRate一起使用,在第一次执行任务之前延迟的毫秒数。

8.initialDelayString

意思initialDelay相同,只是使用字符串的形式。支持配置文件中配置参数,采用占位符获取配置参数的情形

测试类方法

测试类不包含包名,可自行导入,有兴趣的同学还可以观察一下线程ID,可以测试一下多个调度任务线程执行情况。

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@EnableScheduling
public class TestHandleJob {
    
    /**
     *  任务周期3S 模拟作业执行时长 1S
     */
    @Scheduled(cron = "0/3 * * * * ?")
    public void testJobCron() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(1000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }

    /**
     * 3S执行一次 模拟作业执行时长5S
     * 上一次开始执行时间点之后多长时间再执行
     */
    //@Scheduled(fixedRate = 3000L)
    public void testJobFixedRate() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(5000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }

    /**
     * 3S执行一次 模拟作业执行时长5S
     * 上一次执行完毕时间点之后多长时间再执行
     */
    //@Scheduled(fixedDelay = 3000L)
    public void testJobFixedDelay() throws InterruptedException {
        log.info("->TID:{}任务开始{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
        Thread.sleep(5000);
        log.info("<-TID:{}任务结束{}",Thread.currentThread().getId(), DateUtil.currentLongDateTime());
    }


}

你可能感兴趣的:(JAVA,java,cron)