Spring Boot使用Schedule实现定时任务

SpringBoot系列:Spring Boot定时任务Spring Schedule Spring Schedule是Spring提供的定时任务框架,相较于Quartz,Schedule更加简单易用,在中小型应用中,对于大部分需求,Schedule都可以胜任。 一、Spring Schedule使用演示 在SpringBoot使用Spring Schedule非常简单,因为SpringBoot自身的starter中已经集成了Schedule,而不需要我们做更多的处理。 使用@Ena... 阅读详情

GitHub:SpringBootDemo
Gitee:SpringBootDemo
微信公众号:在这里插入图片描述

0. 开发环境

  • IDE:IntelliJ IDEA 2017.1 x64

  • jdk:1.8.0_91

  • Spring Boot:2.1.1.RELEASE


1. 简单定时任务

对于一些比较简单的定时任务,比如固定时间间隔执行固定方法,在标准Java方法上注解@Scheduled即可

package cn.wbnull.springbootdemo.schedule;

import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTask {

    @Scheduled(cron = "0/10 * * * * ?") //每10秒执行一次
    public void scheduledTaskByCorn() {
        LoggerUtils.info("定时任务开始 ByCorn:" + DateUtils.dateFormat());
        scheduledTask();
        LoggerUtils.info("定时任务结束 ByCorn:" + DateUtils.dateFormat());
    }

    @Scheduled(fixedRate = 10000) //每10秒执行一次
    public void scheduledTaskByFixedRate() {
        LoggerUtils.info("定时任务开始 ByFixedRate:" + DateUtils.dateFormat());
        scheduledTask();
        LoggerUtils.info("定时任务结束 ByFixedRate:" + DateUtils.dateFormat());
    }

    @Scheduled(fixedDelay = 10000) //每10秒执行一次
    public void scheduledTaskByFixedDelay() {
        LoggerUtils.info("定时任务开始 ByFixedDelay:" + DateUtils.dateFormat());
        scheduledTask();
        LoggerUtils.info("定时任务结束 ByFixedDelay:" + DateUtils.dateFormat());
    }

    private void scheduledTask() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

然后项目启动类上增加注解@EnableScheduling,表示开启定时任务

package cn.wbnull.springbootdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class SpringBootDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }
}

这里因为我们在ScheduledTask类创建了三个定时任务,@Scheduled默认是不并发执行的,因此我们先注释掉其他,分别进行测试。

1.1 @Scheduled(cron = “0/10 * * * * ?”)

package cn.wbnull.springbootdemo.schedule;

import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTask {

    @Scheduled(cron = "0/10 * * * * ?") //每10秒执行一次
    public void scheduledTaskByCorn() {
        LoggerUtils.info("定时任务开始 ByCorn:" + DateUtils.dateFormat());
        scheduledTask();
        LoggerUtils.info("定时任务结束 ByCorn:" + DateUtils.dateFormat());
    }

    private void scheduledTask() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

启动项目,运行结果如下

[INFO][2019-02-18 16:08:40,095]||定时任务开始 ByCorn:2019-02-18 16:08:40
[INFO][2019-02-18 16:08:45,097]||定时任务结束 ByCorn:2019-02-18 16:08:45
[INFO][2019-02-18 16:08:50,001]||定时任务开始 ByCorn:2019-02-18 16:08:50
[INFO][2019-02-18 16:08:55,003]||定时任务结束 ByCorn:2019-02-18 16:08:55
[INFO][2019-02-18 16:09:00,002]||定时任务开始 ByCorn:2019-02-18 16:09:00
[INFO][2019-02-18 16:09:05,004]||定时任务结束 ByCorn:2019-02-18 16:09:05
[INFO][2019-02-18 16:09:10,001]||定时任务开始 ByCorn:2019-02-18 16:09:10
[INFO][2019-02-18 16:09:15,003]||定时任务结束 ByCorn:2019-02-18 16:09:15
[INFO][2019-02-18 16:09:20,001]||定时任务开始 ByCorn:2019-02-18 16:09:20
[INFO][2019-02-18 16:09:25,002]||定时任务结束 ByCorn:2019-02-18 16:09:25
[INFO][2019-02-18 16:09:30,001]||定时任务开始 ByCorn:2019-02-18 16:09:30
[INFO][2019-02-18 16:09:35,002]||定时任务结束 ByCorn:2019-02-18 16:09:35

我们再改下scheduledTask方法中线程休眠时间,使休眠时间大于定时任务间隔时间Thread.sleep(12000);,然后启动项目,查看运行结果。

[INFO][2019-02-18 16:14:20,080]||定时任务开始 ByCorn:2019-02-18 16:14:20
[INFO][2019-02-18 16:14:32,081]||定时任务结束 ByCorn:2019-02-18 16:14:32
[INFO][2019-02-18 16:14:40,001]||定时任务开始 ByCorn:2019-02-18 16:14:40
[INFO][2019-02-18 16:14:52,002]||定时任务结束 ByCorn:2019-02-18 16:14:52
[INFO][2019-02-18 16:15:00,000]||定时任务开始 ByCorn:2019-02-18 16:15:00
[INFO][2019-02-18 16:15:12,002]||定时任务结束 ByCorn:2019-02-18 16:15:12

我们可以看到,对于cron表达式 来说,如果业务代码执行时间小于定时任务间隔时间,那么定时任务每10秒执行一次,且不受业务代码影响,无论业务代码执行多久,定时任务都是10秒执行一次;

如果业务代码执行时间大于定时任务间隔时间,因定时任务默认不并发,所以一直到业务代码执行完成的那个10秒,定时任务也是整10秒执行一次,不受业务代码影响。

注意:@Scheduled(cron = “0/10 * * * * ?”)控制的每10秒执行一次的定时任务,是每10秒整执行一次,即一分钟内,如果当前秒数能够整除10,则执行定时任务,或理解为每分钟0秒开始执行,10秒后执行下一次,执行完一分钟后,再从0秒开始。即只会在10s,20s,30s…的时候执行,如果配置定时任务@Scheduled(cron = “0/7 * * * * ?”)这种,则只会在0s,7s,14s…的时候执行。

1.2 @Scheduled(fixedRate = 10000)

package cn.wbnull.springbootdemo.schedule;

import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTask {

    @Scheduled(fixedRate = 10000) //每10秒执行一次
    public void scheduledTaskByFixedRate() {
        LoggerUtils.info("定时任务开始 ByFixedRate:" + DateUtils.dateFormat());
        scheduledTask();
        LoggerUtils.info("定时任务结束 ByFixedRate:" + DateUtils.dateFormat());
    }

    private void scheduledTask() {
        try {
            Thread.sleep(12000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

启动项目,运行结果如下

[INFO][2019-02-18 17:33:18,235]||定时任务开始 ByFixedRate:2019-02-18 17:33:18
[INFO][2019-02-18 17:33:23,239]||定时任务结束 ByFixedRate:2019-02-18 17:33:23
[INFO][2019-02-18 17:33:28,191]||定时任务开始 ByFixedRate:2019-02-18 17:33:28
[INFO][2019-02-18 17:33:33,195]||定时任务结束 ByFixedRate:2019-02-18 17:33:33
[INFO][2019-02-18 17:33:38,189]||定时任务开始 ByFixedRate:2019-02-18 17:33:38
[INFO][2019-02-18 17:33:43,191]||定时任务结束 ByFixedRate:2019-02-18 17:33:43
[INFO][2019-02-18 17:33:48,184]||定时任务开始 ByFixedRate:2019-02-18 17:33:48
[INFO][2019-02-18 17:33:53,186]||定时任务结束 ByFixedRate:2019-02-18 17:33:53
[INFO][2019-02-18 17:33:58,190]||定时任务开始 ByFixedRate:2019-02-18 17:33:58
[INFO][2019-02-18 17:34:03,193]||定时任务结束 ByFixedRate:2019-02-18 17:34:03

我们再改下scheduledTask方法中线程休眠时间,使休眠时间大于定时任务间隔时间Thread.sleep(12000);,然后启动项目,查看运行结果。

[INFO][2019-02-18 17:31:30,122]||定时任务开始 ByFixedRate:2019-02-18 17:31:30
[INFO][2019-02-18 17:31:42,122]||定时任务结束 ByFixedRate:2019-02-18 17:31:42
[INFO][2019-02-18 17:31:42,123]||定时任务开始 ByFixedRate:2019-02-18 17:31:42
[INFO][2019-02-18 17:31:54,123]||定时任务结束 ByFixedRate:2019-02-18 17:31:54
[INFO][2019-02-18 17:31:54,124]||定时任务开始 ByFixedRate:2019-02-18 17:31:54
[INFO][2019-02-18 17:32:06,127]||定时任务结束 ByFixedRate:2019-02-18 17:32:06
[INFO][2019-02-18 17:32:06,127]||定时任务开始 ByFixedRate:2019-02-18 17:32:06
[INFO][2019-02-18 17:32:18,134]||定时任务结束 ByFixedRate:2019-02-18 17:32:18

对于fixedRate 来说,如果业务代码执行时间小于定时任务间隔时间,那么定时任务每10秒执行一次,且不受业务代码影响,无论业务代码执行多久,定时任务都是10秒执行一次;

如果业务代码执行时间大于定时任务间隔时间,则定时任务循环执行。

1.3 @Scheduled(fixedDelay = 10000)

package cn.wbnull.springbootdemo.schedule;

import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTask {

    @Scheduled(fixedDelay = 10000) //每10秒执行一次
    public void scheduledTaskByFixedDelay() {
        LoggerUtils.info("定时任务开始 ByFixedDelay:" + DateUtils.dateFormat());
        scheduledTask();
        LoggerUtils.info("定时任务结束 ByFixedDelay:" + DateUtils.dateFormat());
    }

    private void scheduledTask() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

启动项目,运行结果如下

[INFO][2019-02-18 17:45:30,784]||定时任务开始 ByFixedDelay:2019-02-18 17:45:30
[INFO][2019-02-18 17:45:35,792]||定时任务结束 ByFixedDelay:2019-02-18 17:45:35
[INFO][2019-02-18 17:45:45,803]||定时任务开始 ByFixedDelay:2019-02-18 17:45:45
[INFO][2019-02-18 17:45:50,812]||定时任务结束 ByFixedDelay:2019-02-18 17:45:50
[INFO][2019-02-18 17:46:00,814]||定时任务开始 ByFixedDelay:2019-02-18 17:46:00
[INFO][2019-02-18 17:46:05,817]||定时任务结束 ByFixedDelay:2019-02-18 17:46:05
[INFO][2019-02-18 17:46:15,821]||定时任务开始 ByFixedDelay:2019-02-18 17:46:15
[INFO][2019-02-18 17:46:20,825]||定时任务结束 ByFixedDelay:2019-02-18 17:46:20
[INFO][2019-02-18 17:46:30,829]||定时任务开始 ByFixedDelay:2019-02-18 17:46:30
[INFO][2019-02-18 17:46:35,834]||定时任务结束 ByFixedDelay:2019-02-18 17:46:35

我们再改下scheduledTask方法中线程休眠时间,使休眠时间大于定时任务间隔时间Thread.sleep(12000);,然后启动项目,查看运行结果。

[INFO][2019-02-18 17:47:06,871]||定时任务开始 ByFixedDelay:2019-02-18 17:47:06
[INFO][2019-02-18 17:47:18,879]||定时任务结束 ByFixedDelay:2019-02-18 17:47:18
[INFO][2019-02-18 17:47:28,890]||定时任务开始 ByFixedDelay:2019-02-18 17:47:28
[INFO][2019-02-18 17:47:40,896]||定时任务结束 ByFixedDelay:2019-02-18 17:47:40
[INFO][2019-02-18 17:47:50,903]||定时任务开始 ByFixedDelay:2019-02-18 17:47:50
[INFO][2019-02-18 17:48:02,911]||定时任务结束 ByFixedDelay:2019-02-18 17:48:02
[INFO][2019-02-18 17:48:12,917]||定时任务开始 ByFixedDelay:2019-02-18 17:48:12
[INFO][2019-02-18 17:48:24,924]||定时任务结束 ByFixedDelay:2019-02-18 17:48:24

对于fixedDelay 来说,不管业务代码执行时间与定时任务间隔时间熟长熟短,定时任务都会等业务代码执行完成后再开启新一轮定时。


不过,一般大家在使用定时任务时,都是定时任务时间间隔大于业务代码执行时间。

1.4 多说一点

对于固定时间执行的定时任务,比如每天凌晨4点执行,只能使用cron表达式的方式


2. corn表达式

2.1 corn表达式格式

corn表达式格式:秒 分 时 日 月 星期 年(可选)

字段名允许的值允许的特殊字符
秒0-59, - * /
分0-59, - * /
时0-23, - * /
日1-31, - * ? / L W C
月1-12 或 JAN-DEC, - * /
星期1-7 或 SUN-SAT, - * ? / L C #
年(可选)空 或 1970-2099, - * /

释义:

1、*:通配符,表示该字段可以接收任意值。

2、? :表示不确定的值,或不关心它为何值,仅在日期和星期中使用,当其中一个设置了条件时,另外一个用"?" 来表示"任何值"。

3、,:表示多个值,附加一个生效的值。

4、-:表示一个指定的范围

5、/:指定一个值的增量值。例n/m表示从n开始,每次增加m

6、L:用在日期表示当月的最后一天,用在星期"L"单独使用时就等于"7"或"SAT",如果和数字联合使用表示该月最后一个星期X。例如,"0L"表示该月最后一个星期日。

7、W:指定离给定日期最近的工作日(周一到周五),可以用"LW"表示该月最后一个工作日。例如,"10W"表示这个月离10号最近的工作日

8、C:表示和calendar联系后计算过的值。例如:用在日期中,"5C"表示该月第5天或之后包括calendar的第一天;用在星期中,"5C"表示这周四或之后包括calendar的第 一天。

9、#:表示该月第几个星期X。例6#3表示该月第三个周五。

2.2 示例值

0 * * * * ? 每分钟触发

0 0 * * * ? 每小时整触发

0 0 4 * * ? 每天凌晨4点触发

0 15 10 * * ? 每天早上10:15触发

*/5 * * * * ? 每隔5秒触发

0 */5 * * * ? 每隔5分钟触发

0 0 4 1 * ? 每月1号凌晨4点触发

0 0 4 L * ? 每月最后一天凌晨3点触发

0 0 3 ? * L 每周星期六凌晨3点触发

0 11,22,33 * * * ? 每小时11分、22分、33分触发


3. 配置定时任务

对于上面那些简单的定时任务,定时任务的corn表达式写死在代码里,如果要改动表达式,需要修改代码,重新打包发布,比较麻烦。因此,我们可以把corn表达式配置在配置文件中,然后程序读取配置,当需要修改表达式时,只需要修改配置文件即可。

application.yml增加配置

demo:
  corn: 0/11 * * * * ?

定时任务

package cn.wbnull.springbootdemo.schedule;

import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTask {

    @Scheduled(cron = "${demo.corn}")
    public void scheduledTaskByConfig() {
        LoggerUtils.info("定时任务 ByConfig:" + DateUtils.dateFormat());
    }
}

启动项目,运行结果如下

[INFO][2019-02-18 23:47:33,047]||定时任务 ByConfig:2019-02-18 23:47:33
[INFO][2019-02-18 23:47:44,003]||定时任务 ByConfig:2019-02-18 23:47:44
[INFO][2019-02-18 23:47:55,009]||定时任务 ByConfig:2019-02-18 23:47:55
[INFO][2019-02-18 23:48:00,008]||定时任务 ByConfig:2019-02-18 23:48:00
[INFO][2019-02-18 23:48:11,009]||定时任务 ByConfig:2019-02-18 23:48:11
[INFO][2019-02-18 23:48:22,009]||定时任务 ByConfig:2019-02-18 23:48:22
[INFO][2019-02-18 23:48:33,009]||定时任务 ByConfig:2019-02-18 23:48:33

修改application.yml配置

demo:
  corn: 0/23 * * * * ?

启动项目,运行结果如下

[INFO][2019-02-18 23:52:23,089]||定时任务 ByConfig:2019-02-18 23:52:23
[INFO][2019-02-18 23:52:46,008]||定时任务 ByConfig:2019-02-18 23:52:46
[INFO][2019-02-18 23:53:00,009]||定时任务 ByConfig:2019-02-18 23:53:00
[INFO][2019-02-18 23:53:23,002]||定时任务 ByConfig:2019-02-18 23:53:23
[INFO][2019-02-18 23:53:46,009]||定时任务 ByConfig:2019-02-18 23:53:46

定时任务根据配置文件动态变化。


4. 动态修改定时任务

对于有些情况,我们需要在代码中,通过方法动态修改定时任务corn表达式

application.yml配置

demo:
  corn: 0/7 * * * * ?
  cornV2: 0/22 * * * * ?

新建ScheduledTaskV2.java

package cn.wbnull.springbootdemo.schedule;

import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTaskV2 implements SchedulingConfigurer {

    @Value("${demo.corn}")
    private String corn;
    @Value("${demo.cornV2}")
    private String cornV2;

    private int tag = 0;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.addTriggerTask(() -> {
            LoggerUtils.info("定时任务V2:" + DateUtils.dateFormat());
        }, (triggerContext) -> {
            CronTrigger cronTrigger;
            if (tag % 2 == 0) {
                LoggerUtils.info("定时任务V2动态修改corn表达式:" + corn + "," + DateUtils.dateFormat());
                cronTrigger = new CronTrigger(corn);
                tag++;
            } else {
                LoggerUtils.info("定时任务V2动态修改corn表达式:" + cornV2 + "," + DateUtils.dateFormat());
                cronTrigger = new CronTrigger(cornV2);
                tag++;
            }

            return cronTrigger.nextExecutionTime(triggerContext);
        });
    }
}

启动项目,运行结果如下

[INFO][2019-02-19 00:19:49,011]||定时任务V2:2019-02-19 00:19:49
[INFO][2019-02-19 00:19:49,011]||定时任务V2动态修改corn表达式:0/22 * * * * ?,2019-02-19 00:19:49
[INFO][2019-02-19 00:20:00,007]||定时任务V2:2019-02-19 00:20:00
[INFO][2019-02-19 00:20:00,007]||定时任务V2动态修改corn表达式:0/7 * * * * ?,2019-02-19 00:20:00
[INFO][2019-02-19 00:20:07,006]||定时任务V2:2019-02-19 00:20:07
[INFO][2019-02-19 00:20:07,006]||定时任务V2动态修改corn表达式:0/22 * * * * ?,2019-02-19 00:20:07
[INFO][2019-02-19 00:20:22,008]||定时任务V2:2019-02-19 00:20:22
[INFO][2019-02-19 00:20:22,008]||定时任务V2动态修改corn表达式:0/7 * * * * ?,2019-02-19 00:20:22
[INFO][2019-02-19 00:20:28,010]||定时任务V2:2019-02-19 00:20:28
[INFO][2019-02-19 00:20:28,010]||定时任务V2动态修改corn表达式:0/22 * * * * ?,2019-02-19 00:20:28
[INFO][2019-02-19 00:20:44,003]||定时任务V2:2019-02-19 00:20:44
[INFO][2019-02-19 00:20:44,003]||定时任务V2动态修改corn表达式:0/7 * * * * ?,2019-02-19 00:20:44
[INFO][2019-02-19 00:20:49,004]||定时任务V2:2019-02-19 00:20:49
[INFO][2019-02-19 00:20:49,004]||定时任务V2动态修改corn表达式:0/22 * * * * ?,2019-02-19 00:20:49
[INFO][2019-02-19 00:21:00,011]||定时任务V2:2019-02-19 00:21:00
[INFO][2019-02-19 00:21:00,011]||定时任务V2动态修改corn表达式:0/7 * * * * ?,2019-02-19 00:21:00
[INFO][2019-02-19 00:21:07,011]||定时任务V2:2019-02-19 00:21:07
[INFO][2019-02-19 00:21:07,011]||定时任务V2动态修改corn表达式:0/22 * * * * ?,2019-02-19 00:21:07

成功通过代码动态修改corn表达式且运行结果正确。


5. 并发执行定时任务

回到我们 1. 简单定时任务 中创建的三个定时任务,当时因为@Scheduled默认是不并发执行的,所以我们先注释掉了其他定时任务,分别进行的测试。

那我们实际开发中,确实创建了多个定时任务,且想并发执行时,该怎么做呢?

定时任务类添加注解@EnableAsync,需并发执行的定时任务方法添加注解@Async

新建定时任务类ScheduledTaskV3

package cn.wbnull.springbootdemo.schedule;

import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@EnableAsync
public class ScheduledTaskV3 {

    @Scheduled(cron = "0/7 * * * * ?")
    @Async
    public void scheduledTaskV1() {
        LoggerUtils.info("定时任务V3,定时任务1开始:" + DateUtils.dateFormat());
        scheduledTask();
        LoggerUtils.info("定时任务V3,定时任务1结束:" + DateUtils.dateFormat());
    }

    @Scheduled(cron = "0/10 * * * * ?")
    @Async
    public void scheduledTaskV2() {
        LoggerUtils.info("定时任务V3,定时任务2开始:" + DateUtils.dateFormat());
        scheduledTask();
        LoggerUtils.info("定时任务V3,定时任务2结束:" + DateUtils.dateFormat());
    }

    @Scheduled(cron = "0/22 * * * * ?")
    @Async
    public void scheduledTaskV3() {
        LoggerUtils.info("定时任务V3,定时任务3开始:" + DateUtils.dateFormat());
        scheduledTask();
        LoggerUtils.info("定时任务V3,定时任务3结束:" + DateUtils.dateFormat());
    }

    private void scheduledTask() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

启动项目,运行结果如下

[INFO][2019-02-19 00:36:21,077]||定时任务V3,定时任务1开始:2019-02-19 00:36:21
[INFO][2019-02-19 00:36:22,003]||定时任务V3,定时任务3开始:2019-02-19 00:36:22
[INFO][2019-02-19 00:36:26,078]||定时任务V3,定时任务1结束:2019-02-19 00:36:26
[INFO][2019-02-19 00:36:27,006]||定时任务V3,定时任务3结束:2019-02-19 00:36:27
[INFO][2019-02-19 00:36:28,003]||定时任务V3,定时任务1开始:2019-02-19 00:36:28
[INFO][2019-02-19 00:36:30,003]||定时任务V3,定时任务2开始:2019-02-19 00:36:30
[INFO][2019-02-19 00:36:33,003]||定时任务V3,定时任务1结束:2019-02-19 00:36:33
[INFO][2019-02-19 00:36:35,004]||定时任务V3,定时任务1开始:2019-02-19 00:36:35
[INFO][2019-02-19 00:36:35,005]||定时任务V3,定时任务2结束:2019-02-19 00:36:35
[INFO][2019-02-19 00:36:40,003]||定时任务V3,定时任务2开始:2019-02-19 00:36:40
[INFO][2019-02-19 00:36:40,005]||定时任务V3,定时任务1结束:2019-02-19 00:36:40
[INFO][2019-02-19 00:36:42,001]||定时任务V3,定时任务1开始:2019-02-19 00:36:42
[INFO][2019-02-19 00:36:44,003]||定时任务V3,定时任务3开始:2019-02-19 00:36:44
[INFO][2019-02-19 00:36:45,004]||定时任务V3,定时任务2结束:2019-02-19 00:36:45
[INFO][2019-02-19 00:36:47,002]||定时任务V3,定时任务1结束:2019-02-19 00:36:47
[INFO][2019-02-19 00:36:49,002]||定时任务V3,定时任务1开始:2019-02-19 00:36:49
[INFO][2019-02-19 00:36:49,004]||定时任务V3,定时任务3结束:2019-02-19 00:36:49
[INFO][2019-02-19 00:36:50,001]||定时任务V3,定时任务2开始:2019-02-19 00:36:50

定时任务能够并发执行。


微信:https://mp.weixin.qq.com/s/qJZpCjcZYQWnmDkztiA_uQ

微博:https://weibo.com/ttarticle/p/show?id=2309404446645717696521

知乎:https://zhuanlan.zhihu.com/p/95813468


一看就懂!Springboot使用@Schedule定时执行任务 这几天做了一个谷歌验证码的小项目,由于验证码是每30秒刷新的。一开始采用的是前端发送刷新请求,获取时间戳后倒计时,但是发现会出现bug,由于谷歌那边是每0s和每30s准时刷新,但是我的是根据用户访问网页时候才发送刷新请求,就会导致会有时间差。于是又改成用@Schedule来定时刷新,前端只负责获取到验证码和时间戳,不再对系统进行操纵。 下面来说说如何使用@Schedule 了解一个新玩意最好的... 阅读详情

相关推荐

告别“单打独斗”:Oh My Open Code 如何用多模型协作重塑 AI 编程范式

介绍"Oh My OpenCode"——一个能协调多个专业AI模型完成复杂开发任务的智能编程框架。您将看到它如何分配任务、发挥不同模型的独特优势,并通过并行处理和实时纠错等功能解决AI编程流程中的常见痛点。

老孙 | Ethan Sun 的博客:AI 智能体与 AI 原生软件的工程实践 4208

SpringBoot Schedule的三种使用方式

SpringBoot Schedule的三种使用方式

qq_31794615的博客 4878

Flink on k8s 环境搭建(一)

Flink on Yarn的环境搭建过程中,需要进行配置较多,且需要搭建zookeeper Hadoop Yarn 等相关组件,安装流程比较复杂,集群出现问题重新安装的流程也比较复杂,且Yarn的3个节点中 只能起了 3个resourceManager和1个NodeManager,Flink 作业申请资源时只能 向NodeManager的节点申请资源,整体有资源瓶颈的隐患(后继flink作业会越来越多),现在尝试进行Flink on k8s 的环境搭建。

wangqiaowq的博客 3413

Springboot定时任务 @Scheduled

我们在平常项目开发中,经常会用到周期性定时任务,这个时候使用定时任务就能很方便的实现。在SpringBoot中用得最多的就是Schedule。

weixin_50888407的博客 4424

不只是烧录:深入理解英飞凌Aurix MCU的HSM安全模块与UDE Memtool解锁操作

本文深入探讨了英飞凌Aurix MCU的HSM安全模块设计与UDE Memtool解锁操作,揭示了硬件安全模块的架构、安全启动链机制及调试接口的安全特性。通过分析UDE Memtool的解锁逻辑和量产环境下的最佳实践,帮助工程师更好地应对MCU锁定问题,提升汽车电子和工业控制领域的安全烧录效率。

weixin_32770423的博客 296

2025最新正版Autodesk 3ds Max 2022安装教程:从下载到中文环境配置全流程解析

Autodesk 3ds Max 2022是一款专业的三维建模、动画和渲染软件,广泛应用于影视制作、游戏开发、建筑可视化等领域。

waicsdn_haha的博客 1万+

php schedule 只执行一次_Spring Boot使用Schedule实现定时任务

0. 开发环境 IDE:IntelliJ IDEA 2017.1 x64 jdk:1.8.0_91 Spring Boot:2.1.1.RELEASE 1. 简单定时任务对于一些比较简单的定时任务,比如固定时间间隔执行固定方法,在标准Java方法上注解@Scheduled即可package cn.wbnull.springbootdemo.schedule; import cn.wbnull.s...

weixin_39887846的博客 390

从零到一:龙芯杯参赛全攻略(含北理工学长经验PDF、B站培训视频与开源代码合集)

本文详细介绍了龙芯杯全国大学生计算机系统能力大赛的参赛全攻略,包括资源整合、技能树构建、团队协作和避坑指南。提供北理工学长经验PDF、B站培训视频与开源代码合集,帮助参赛者从零基础到站上领奖台。重点解析如何高效获取优质资源、避开新手常见陷阱及构建可落地的学习路径,助力普通学生系统学习CPU设计。

weixin_26802933的博客 538

spring boot + Schedule简单定时任务实现

1、启动类加注解@EnableScheduling package cn.sunline.insd.sso.service; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.sp

JAVA圈的博客 1149

关于token无痛刷新的两个方案

目录方案一方案二 方案一 思路: 后端需要返回一个token过期的时间,在请求发起前拦截每个请求,判断token的有效时间是否已经过期,如果已过期,则暂时将请求挂起,先刷新token后再继续请求。 前期思考: 返回过期时间是为了判断是否过期的,但是如果服务器时间和系统时间不一致呢? 如果同时发起多个请求时怎么办? 实现: 因为是在请求前进行拦截,所以这里用axios的axios.interceptors.request.use()方法 首先,关于服务器时间和系统时间不一致的问题,我的解决方法是:

Yugoup的博客 2715

VisionMaster4.2.0与C#控件开发实战:从入门到精通的完整指南

本文详细介绍了VisionMaster4.2.0与C#控件开发的实战指南,从基础环境搭建到核心控件使用,再到高级功能实现。通过VmFrontendControl、VmGlobalToolControl等核心控件的深入解析,帮助开发者快速掌握机器视觉应用开发技巧,提升开发效率。特别适合需要集成VisionMaster4.2.0 SDK进行视觉系统开发的C#程序员。

weixin_42665725的博客 383

springboot schedule动态实现_基于Spring Boot实现定时任务的动态增删启停

今天跟大家分享基于Spring Boot实现定时任务的动态增删启停的知识。1基于Spring Boot实现定时任务的动态增删启停在spring boot项目中,可以通过@EnableScheduling注解和@Scheduled注解实现定时任务,也可以通过SchedulingConfigurer接口来实现定时任务。但是这两种方式不能动态添加、删除、启动、停止任务。要实现动态增删启停定时...

weixin_29763641的博客 950

手把手教你学simulink实例--基于Simulink的储能系统性能评估与仿真

储能系统是现代能源体系中的关键组成部分,广泛应用于可再生能源并网、电网调峰调频、电力质量改善以及电动汽车充电等领域。为了提高储能系统的运行效率和可靠性,对其性能进行准确评估至关重要。基于MATLAB/Simulink平台,可以构建储能系统的动态模型,并通过仿真分析其在不同工况下的性能表现。本项目旨在研究储能系统的建模方法、控制策略及其性能评估指标,并通过Simulink仿真验证系统的动态特性和稳态性能。

MHD0815的博客 194

java实现定时任务 schedule_Spring Boot 实现定时任务的 4 种方式

作者:Wan QingHuawanqhblog.top/2018/02/01/SpringBootTaskSchedule/定时任务实现的几种方式:Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。ScheduledExecuto...

weixin_39883670的博客 220

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Spring boot Schedule corn 实现定时任务

@Component @EnableScheduling public class ScheduleTaskService { @Autowired BillingService billingService; @Scheduled(cron = "0 35 10 * * ? ") public void autosync() { billingService....

ss654271961的博客 671

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

SpringBoot定时任务 - Spring Schedule实现方式

这种情况会发生在,比如你调用一个第三方接口,没有设置调用超时,继而引发异常,这时候当前任务便阻塞了。以CronTask为例,如果定义了taskScheduler则由taskScheduler执行,如果没有放到unresolvedTasks中。ScheduledTaskRegistrar最主要的是注册各种类型的task (这种方式在新的版本中已经废弃了)获取到方法上Scheduled注解(对任务的定义),通过processScheduled处理具体类型的task。注册哪些Task,怎么设计类的呢?

埃泽漫笔 937

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

springboot schedule动态实现_Spring Boot实现动态增删启停定时任务

点击上方☝SpringForAll社区轻松关注!及时获取有趣有料的技术文章本文来源:https://www.jianshu.com/p/0f68936393fd在spring boot项目中,可以通过@EnableScheduling注解和@Scheduled注解实现定时任务,也可以通过SchedulingConfigurer接口来实现定时任务。但是这两种方式不能动态添加、删除、启动、...

weixin_39868959的博客 203

定时任务schedule(spring boot )

定时任务schedule(spring boot ) 1. 定时任务实现方式:SpringBoot自带的Scheduled,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多,本文主要介绍。 执行方式:单线程(串行)------------多个定时任务,一个跑完,其他的才能跑多线程(并行) 2. 创建定时任务 @Comp...

诸葛子房的博客 373

springboot schedule动态实现_Spring Boot 实现定时任务的动态增删启停!

来源:https://www.jianshu.com/p/0f68936393fd添加执行定时任务的线程池配置类添加定时任务示例类定时任务数据库表设计添加定时任务实体类新增定时任务在spring boot项目中,可以通过@EnableScheduling注解和@Scheduled注解实现定时任务,也可以通过SchedulingConfigurer接口来实现定时任务。但是这两种方式不能动态...

weixin_39779032的博客 580

【Springboot知识】Springboot计划任务Schedule详解

Overridelog.error("定时任务执行失败: {}", ex.getMessage());// 发送告警通知。

wendao76的专栏 1505

SpringBoot中使用Schedule

一、基本方法 有了SpringBoot貌似一切都变了非常简单,定时任务也不用整合quartz了,直接schedule就欧了。具体咋用?非常简单。 1、引入POM依赖 Spring的Schedule包含在spring-boot-starter模块中,无需引入其他依赖。 2、开启注解支持 在启动类增加注解:@EnableScheduling 3、轻松上手使用 A、Cron表达式 ...

tobearc的专栏 7056

SpringBoot两种定时任务(Spring Schedule 与 Quartz 整合 )实现

前言 最近在项目中使用到定时任务,之前一直都是使用Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Schedule 可以帮助我们实现简单的定时任务功能。 下面说一下两种方式在Spring Boot 项目中的使用。 Spring Schedule 实现定时任务 Spring Schedule 实现定时任务有两种方式 1. 使用XML配置定时任务, 2. 使用 @Scheduled 注解。 因为是Spring Boot 项目 可能尽量避免使用XML配置的形式,主要说

liinux-Talk is cheap,show me the code. 540
上一篇: Spring Boot整合MyBatis连接数据库
下一篇: Java 调用 WebService
程序员null
博客等级 码龄11年 1304粉丝 124原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值