SpringBoot最简单的定时任务@Scheduler的使用及解读

 更新时间:2025年03月22日 10:50:14   作者:七年·  
这篇文章主要介绍了SpringBoot最简单的定时任务@Scheduler的使用及解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

SpringBoot定时任务@Scheduler

Spring Boot 中一般来说定时任务使用@Scheduler注解或者Quartz框架,或者自定义线程实现,最简单的当属@Scheduler注解

  • 依赖:
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
  • 创建Application:
@SpringBootApplication
//此注解开启异步定时任务,必须要有
@EnableScheduling
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • 创建任务:
@Component
public class SpringJob {
    //springboot扫描到这个注解就会按照定义的计划去执行任务
    //cron是cron表达式,因为很简单但是描述要话费比较多的篇幅,所以略
    @Scheduled(cron = "0/1 * * * * ?")
    public void myJob(){
        //任务处理逻辑
        System.out.println(new Date() +"Spring Scheduler 执行");
    }
}
  • 启动 Application:

上述是一个最简单的单job cron调度的实现.

  • @Scheduler中的参数:
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 "";
String cron() default “”;接收一个cron表达式字符串,以cron表达式调度任务
String zone() default “”;设置时区,不设置的话cron就基于服务器所在的本地时区
long fixedDelay() default -1;设置任务间隔时间(毫秒),就是任务结束后再过多久开始新的任务
String fixedDelayString() default “”;同 long fixedDelay(),只是把参数从long改成string
long fixedRate() default -1;设置任务每隔多久开启
String fixedRateString() default “”;同 long fixedRate() 只是把参数从long改成string
long initialDelay() default -1;第一次执行延迟时间(启动后多久才开始任务)
String initialDelayString() default “”;同 long initialDelay()
  • spring boot 默认开启一个线程执行任务:
@Component
public class SpringJob {

    @Scheduled(fixedRateString = "1000")
    public void myJob2() throws InterruptedException {
        System.out.println(new Date() +" job开启");
        Thread.sleep(2000);
        System.out.println(new Date() +" job结束");
    }
}

执行结果:
Fri Jul 31 10:34:16 CST 2020 job开启
Fri Jul 31 10:34:18 CST 2020 job结束
Fri Jul 31 10:34:18 CST 2020 job开启
Fri Jul 31 10:34:20 CST 2020 job结束
Fri Jul 31 10:34:20 CST 2020 job开启
Fri Jul 31 10:34:22 CST 2020 job结束
Fri Jul 31 10:34:22 CST 2020 job开启
Fri Jul 31 10:34:24 CST 2020 job结束
Fri Jul 31 10:34:24 CST 2020 job开启
Fri Jul 31 10:34:26 CST 2020 job结束
Fri Jul 31 10:34:26 CST 2020 job开启
Fri Jul 31 10:34:28 CST 2020 job结束
Fri Jul 31 10:34:28 CST 2020 job开启
Fri Jul 31 10:34:30 CST 2020 job结束

设置的任务为每隔1秒中开启一次,一次任务执行时间是2秒,但是发现执行的过程是,同一时间只有一个线程在执行.也就是单线程执行

  • 现在执行两个job,单线程情况下,自然也是无法并发的:
@Component
public class SpringJob {
    @Scheduled(fixedRateString  = "2000")
    public void myJob() throws InterruptedException {
        System.out.println(new Date() +" job1开始");
        Thread.sleep(10000);
        System.out.println(new Date() +" job1结束");
    }
    @Scheduled(fixedRateString = "1000")
    public void myJob2() throws InterruptedException {
        System.out.println(new Date() +" job2开启");
        Thread.sleep(2000);
        System.out.println(new Date() +" job2结束");
    }
}
执行结果:
Fri Jul 31 10:51:56 CST 2020 job1开始
Fri Jul 31 10:52:06 CST 2020 job1结束
Fri Jul 31 10:52:06 CST 2020 job2开启
Fri Jul 31 10:52:08 CST 2020 job2结束
Fri Jul 31 10:52:08 CST 2020 job2开启
Fri Jul 31 10:52:10 CST 2020 job2结束
Fri Jul 31 10:52:10 CST 2020 job1开始
Fri Jul 31 10:52:20 CST 2020 job1结束
Fri Jul 31 10:52:20 CST 2020 job2开启
Fri Jul 31 10:52:22 CST 2020 job2结束
Fri Jul 31 10:52:22 CST 2020 job2开启
Fri Jul 31 10:52:24 CST 2020 job2结束

任务的每次执行,无论是单个任务多次执行,还是多个任务一次执行,对于线程来说都是一样的,都需要开启一个线程.有几个线程就可以几个任务(或者相同任务的多次)并发执行

默认情况下,scheduler只有一个线程

  • 自定义线程池,添加一个配置类:
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(setExecutor());
    }
    @Bean
    public Executor setExecutor() {
        //设置线程个数,这里我们设置5个(同一时间可以并行执行5个线程)
        return Executors.newScheduledThreadPool(5);
    }
}
  • 此时执行上方的单个任务:

Fri Jul 31 10:55:18 CST 2020 job开启
Fri Jul 31 10:55:20 CST 2020 job结束
Fri Jul 31 10:55:20 CST 2020 job开启
Fri Jul 31 10:55:22 CST 2020 job结束
Fri Jul 31 10:55:22 CST 2020 job开启
Fri Jul 31 10:55:24 CST 2020 job结束
Fri Jul 31 10:55:24 CST 2020 job开启
Fri Jul 31 10:55:26 CST 2020 job结束

单个任务还是只能串行执行.

  • 执行上方的两个任务:

Fri Jul 31 10:59:59 CST 2020 job2开启
Fri Jul 31 10:59:59 CST 2020 job1开始
Fri Jul 31 11:00:01 CST 2020 job2结束
Fri Jul 31 11:00:01 CST 2020 job2开启
Fri Jul 31 11:00:03 CST 2020 job2结束
Fri Jul 31 11:00:03 CST 2020 job2开启
Fri Jul 31 11:00:05 CST 2020 job2结束
Fri Jul 31 11:00:05 CST 2020 job2开启
Fri Jul 31 11:00:07 CST 2020 job2结束
Fri Jul 31 11:00:07 CST 2020 job2开启
Fri Jul 31 11:00:09 CST 2020 job1结束
Fri Jul 31 11:00:09 CST 2020 job1开始
Fri Jul 31 11:00:09 CST 2020 job2结束

发现任务跟job1与job2之间是可以并发执行的.但是对于job1的多次任务,job2的多次任务,都是串行执行的.

现在线程池中有多个线程,job与job之间可以并发,如何让单个job的多次可以并发执行,就需要@Async注解,此注解要用在job的方法上.@EnableAsync注解,此注解要在Application类上,此时,job的多次执行也可以并发执行了.

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

@Component
public class SpringJob {
    @Async   
    @Scheduled(fixedRateString = "2000")
    public void myJob() throws InterruptedException {
        System.out.println(new Date() + " job1开始");
        Thread.sleep(10000);
        System.out.println(new Date() + " job1结束");
    }
    
    @Scheduled(fixedRateString = "1000")
    public void myJob2() throws InterruptedException {
        System.out.println(new Date() + " job2开启");
        Thread.sleep(2000);
        System.out.println(new Date() + " job2结束");
    }
}
执行结果:
Fri Jul 31 11:08:57 CST 2020 job2开启
Fri Jul 31 11:08:57 CST 2020 job1开始
Fri Jul 31 11:08:59 CST 2020 job1开始
Fri Jul 31 11:08:59 CST 2020 job2结束
Fri Jul 31 11:08:59 CST 2020 job2开启
Fri Jul 31 11:09:01 CST 2020 job1开始
Fri Jul 31 11:09:01 CST 2020 job2结束
Fri Jul 31 11:09:01 CST 2020 job2开启
Fri Jul 31 11:09:03 CST 2020 job1开始
Fri Jul 31 11:09:03 CST 2020 job2结束
Fri Jul 31 11:09:03 CST 2020 job2开启

可以发现job1在前一次没有执行完时,就已经开始执行了.

重要一点

自定线程池Configuration是为了启用多线程,此时可以起到job1与job2之间的并发执行,但是job1多次任务只能串行执行,所以才增加了@Aysnc跟@EnableAsync注解.

@EnableAsync注解有两个作用,1单线程变多线程,2 可以允许单个job多次运行时并行执行(需要再加@Async),如果已经是多线程了,但是不加此注解,同一个job的多次执行还是串行.

其实在使用@EnableAsync注解的时候,springboot会把自定义的configuration给覆盖掉,即使在configuration中配置了单个线程,任务的并发也不会受到影响.所以推荐使用@EnableAsync来完成多线程配置再加@Aysnc来完成任务的并发.

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java操作Apache druid的实例代码

    java操作Apache druid的实例代码

    这篇文章主要介绍了java操作Apache druid的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • SpringBoot之使用枚举参数案例详解

    SpringBoot之使用枚举参数案例详解

    这篇文章主要介绍了SpringBoot之使用枚举参数案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • Spring Boot 数据校验@Valid+统一异常处理的实现

    Spring Boot 数据校验@Valid+统一异常处理的实现

    这篇文章主要介绍了Spring Boot 数据校验@Valid+统一异常处理的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • springboot项目中mybatis-plus@Mapper注入失败问题

    springboot项目中mybatis-plus@Mapper注入失败问题

    这篇文章主要介绍了springboot项目中mybatis-plus@Mapper注入失败问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Spring排序机制之接口与注解的使用方法

    Spring排序机制之接口与注解的使用方法

    本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例,并指导如何选择合适的排序机制来控制Bean的加载顺序和优先级,感兴趣的朋友一起看看吧
    2025-02-02
  • 一文详解kafka序列化器和拦截器

    一文详解kafka序列化器和拦截器

    这篇文章主要为大家介绍了kafka序列化器和拦截器使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • JAVA swing布局管理器实例解析

    JAVA swing布局管理器实例解析

    这篇文章主要介绍了JAVA swing布局管理器实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Spring Boot整合Bootstrap的超详细步骤

    Spring Boot整合Bootstrap的超详细步骤

    之前做前端开发,在使用bootstrap的时候都是去官网下载,然后放到项目中,在页面引用,下面这篇文章主要给大家介绍了关于Spring Boot整合Bootstrap的超详细步骤,需要的朋友可以参考下
    2023-05-05
  • Java中一个线程执行死循环有什么后果

    Java中一个线程执行死循环有什么后果

    这篇文章主要为大家详细介绍了Java中一个线程执行死循环有什么后果,当一个线程在执行死循环时会影响另外一个线程吗,下面为大家揭晓
    2016-05-05
  • 可视化定时任务quartz集成解析全过程

    可视化定时任务quartz集成解析全过程

    在开发中有很多定时任务都不是写死的而是可以人为配置并且写到数据库中的,下面这篇文章主要给大家介绍了关于可视化定时任务quartz集成解析的相关资料,需要的朋友可以参考下
    2022-10-10

最新评论