SpringBoot 定时器

spring提供了@Scheduled@EnableScheduling两个注解用来快速开发定时器,使用很简单

用法: 1、Springboot的启动类中加上@EnableScheduling注解。

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

2、需要定时执行的方法上加上@Scheduled注解,这个注解中可以指定定时执行的规则。

案例

@EnableScheduling
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
@Component
public class Test {

    //每秒执行一次
    @Scheduled(fixedRate = 1000)
    public void schedule(){
        System.out.println("定时执行任务: " + System.currentTimeMillis());
    }
}

启动springboot项目,运行查看日志输出,每秒会输出一次:

定时执行任务: 1661825432538
定时执行任务: 1661825433540
定时执行任务: 1661825434538

定时规则

@Scheduled可以用来配置定时器的执行规则,@Scheduled中主要有9个参数,

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {

   String CRON_DISABLED = ScheduledTaskRegistrar.CRON_DISABLED;

   String cron() default "";

   String zone() default "";

   long fixedDelay() default -1;

   String fixedDelayString() default "";

   long fixedRate() default -1;

   String fixedRateString() default "";

   long initialDelay() default -1;

   String initialDelayString() default "";

   TimeUnit timeUnit() default TimeUnit.MILLISECONDS;

}

1、cron

该参数接收一个cron表达式,cron表达式是一个字符串,字符串是以5或6个空格隔开,分开共6或7个域,每个域代表一个含义

语法

注:其中[年]不是必须的域,可以省略[年]

必填允许值允许通配符
0-59, – * /
0-59, – * /
0-23, – * /
1-31, – * ? / L W
1-12/JAN-DEC, – * /
1-7/SUM-SAT, – * ? / L #
1970-2099, – * /

通配符

*:表示所有值,例如在分字段上设置*,表示每一分钟都会触发

?:表示不指定值,使用的为不需要关心当前设置这个字段的值,例如,要在每月的5号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为?,具体设置为 0 0 0 5 * ?

-:表示区间,例如在小时上设置”10-12″,表示10,11,12点都会触发

,:表示指定多个值,例如在周字段上设置”MON,WED,FRI”表示周一,周三和周五触发

/:用于递增触发,如在秒上面设置”5/15″表示从5秒开始,每增15秒触发(5,20,35,50),在日字段上设置’1/3’所示每月1号开始,每隔三天触发一次。

L:表示最后的意思,在日字段的设置上,表示当月的最后一天(依据当前月份,如果是二月还会依据是否是润年,在周字段上表示星期六,相当于7SAT,如果在L前加上数字,则表示该数据的最后一个,例如在周字段上设置6L这样的格式,则表示本月最后一个星期五)

W:表示离指定日期的最近那个工作日(周一至周五),例如在日字段上置15W,表示离每月15号最近的那个工作日触发,如果15号正好是周六,则找最近的周五(14号)触发,如果15号是周日,则找最近的下周一(16日)触发,如查15号正好是工作日(周一至再周五),则就在该天触发,如果指定格式为1W,它则表示每月1号往后最近的工作日触发,如果1号是周六,则将在3号即下周一触发,W前只能设置具体的数字,不允许区间-

#:序号(表示每月的第几个周几),例如在周字段上设置“6#3”表示在每月的第三个周六,LW可以组合使用,如果在日字段上设置LW,则表示在本月的最后一个工作日触发,

示例

每隔5秒执行一次

*/5 * * * * ?

每隔1分钟执行一次

0 */1 * * * ?

每天23点执行一次

0 0 23 * * ?

每天凌晨1点执行一次

0 0 1 * * ?

每月1号凌晨1点执行一次

0 0 1 1 * ?

每月最后一天23点执行一次

0 0 23 L * ?

每周星期六凌晨1点执行一次

0 0 1 ? * L

在26分,29分,33分执行一次

0 26,29.33 * * * ?

每天的0点,13点,18点,21点都执行一次

0 0 0,13,18,21 * * ?

2、fixedDelay

表示上一次执行完毕时间点之后多长时间执行

@Scheduled(fixedDelay = 5000) //上一次执行完毕时间点之后5秒执行

3、fixedDelayString

fixedDelay一样,只不过fixedDelayString使用字符串的形式,另外fixedDelayString支持占位符

@Scheduled(fixedDelayString = "5000") //上一次执行完毕时间点之后5秒执行

4、fixedRate

表示上次执行时间点之后多长时间再执行

@Scheduled(fixedRate = 5000) //上一次执行时间点之后5秒执行

5、fixedRateString

fixedRate所表示的意思一样,只不过fixedRateString使用的是字符串,同时fixedRateString支持占位符

6、initialDelay

第一次延迟多长时间后再执行

//第一次延迟1秒后执行,之后按fixedRate的规则每5秒执行一次
@Scheduled(initialDelay = 1000, fixedRate = 5000)

自定义线程池

默认情况下,只有一个线程来执行定时器的任务,在只一个线程的情况下,如果有多个定时任务需要执行,就会出现定时任务排队使用,如果有线定时任务的执行时间过长,就会导致其它任务的执行不能按照既定的时间进行执行,如:

@Component
public class Test {

    //每秒执行一次
    @Scheduled(fixedRate = 1000)
    public void schedule(){
        System.out.println(Thread.currentThread() + " 定时执行任务1: " + System.currentTimeMillis());
    }

    @Scheduled(fixedRate = 1000)
    public void se2(){
        System.out.println(Thread.currentThread() + " 定时执行任务2: " + System.currentTimeMillis());
    }

    @Scheduled(fixedRate = 1000)
    public void se3() throws InterruptedException{
        //耗时2秒,模拟耗时操作
        Thread.sleep(2000);
        System.out.println(Thread.currentThread() + " 定时执行任务3: " + System.currentTimeMillis());
    }
}

运行输出:

Thread[scheduling-1,5,main] 定时执行任务3: 1661910086110
Thread[scheduling-1,5,main] 定时执行任务1: 1661910086110
Thread[scheduling-1,5,main] 定时执行任务2: 1661910086110
Thread[scheduling-1,5,main] 定时执行任务3: 1661910088111
Thread[scheduling-1,5,main] 定时执行任务1: 1661910088111
Thread[scheduling-1,5,main] 定时执行任务2: 1661910088111

从输出结果可以看出,由于se3的定时任务执行任务花费了2秒,从而导致了其它两个定时任务的执行时间也间隔了2秒。这就是只有一个线程执行定时任务排队执行任务所造成的结果,

为了解决定时任务排队的问题,我们可以通过自定义线程池来解决这个问题

@Configuration
public class ScheduleConfig {

    @Bean
    public ScheduledExecutorService scheduledExecutorService(){
        //设置并行执行的任务数量
        int corePoolSize = 10;
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    
}

再次运行输出:

Thread[pool-1-thread-2,5,main] 定时执行任务1: 1661910879971
Thread[pool-1-thread-4,5,main] 定时执行任务2: 1661910880971
Thread[pool-1-thread-5,5,main] 定时执行任务1: 1661910880971
Thread[pool-1-thread-1,5,main] 定时执行任务3: 1661910880971
Thread[pool-1-thread-2,5,main] 定时执行任务2: 1661910881971
Thread[pool-1-thread-1,5,main] 定时执行任务1: 1661910881971
Thread[pool-1-thread-6,5,main] 定时执行任务3: 1661910882973

从运行输出结果可以看出,任务1,2,3分别运行于不同的线程中,因此执行互不影响。

原创文章,作者:jiafegn,如若转载,请注明出处:https://www.techlearn.cn/archives/492

Previous 2023年4月5日
Next 2023年4月23日

相关推荐

  • SpringBoot 整合Druid数据源

    简介 Druid是阿里巴巴开源的数据库连接池,号称是Java语言中最好的数据库连接池,能够提供强大的监控和扩展功能。 优点 引入依赖 这里使用的是SpringBoot整合版的Dru…

    2023年3月26日
    169
  • Springboot 注解大全-@Import

    作用 @Import可以用来批量导入需要注册的各种类,如普通的类、配置类,完成普通类和配置类中所有bean注册到spring容器中。作用范围:作用于类、注解 定义 参数 value…

    springboot 2022年8月15日
    184
  • SpringBoot 打包

    SpringBoot 项目部署到服务器常见的方式就是,打包成 jar 包,通过 nohup java -jar 命令去运行项目,这也是官方推荐的一种方式。 导入依赖 打包 设置打包…

    springboot 2023年4月5日
    148
  • SpringBoot Spring Event 业务解耦神器

    介绍 Spring Event是Spring框架中的一个事件机制,主要用于实现应用程序内部的事件传递与处理,它允许不同组件之间通过发布-订阅机制进行解耦通信,比如用户注册,订单创建…

    springboot 2024年1月11日
    301
  • SpringBoot 注解 @Autowired

    作用 实现依赖注入查找方式:@Autowired是先到容器查找类型,如果该类型只有一个那么就直接注入,有多个时再根据名字找使用范围:构造器、方法、参数、字段、注解参数:requir…

    springboot 2022年9月9日
    404
  • SpringBoot CRUD基础开发 入门

    需求简介 环境准备 1、新建项目 新建一个crud的项目,如下: 2、新建数据库脚本 新建curd数据库 初始化数据库 引入依赖 1、引入web依赖 2、引入Lombok依赖 3、…

    2023年3月26日
    178
  • Springboot 注解 @ConfigurationProperties

    作用 @ConfigurationProperties注解主要作用就是将prefix属性指定的前缀配置项的值绑定到这个Bean上,默认情况下需要和@Component或者@Conf…

    springboot 2022年9月2日
    181
  • SpringBoot 单元测试

    简介 Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库,在 Spring Boot 2.2.0 版本之前,spring-boot-starter…

    springboot 2023年4月2日
    242
  • SpringBoot 整合RocketMQ

    简介 使用RocketMQ有两种方式,一种是引入rocketmq-client需要自己创建生产者和消费者,相对来说比较繁琐;另一种是引入rocketmq-spring-boot-s…

    springboot 2023年4月30日
    311
  • SpringBoot 分布式Session

    简介 现在随着分布式,微服务架构的日益成熟,越来越多的企业将传统的单体服务改造为微服务或是分布式架构,在分布式中就遇到session管理的问题,微服务架构中一个服务为了实现高可用至…

    springboot 2023年4月30日
    176