SpringBoot定时任务详解

SpringBoot定时任务详解

记录

使用springboot创建定时任务非常简单,目前主要有以下三种方式创建:

一、基于注解(@Scheduled)

二、基于接口(SchedulingConfigurer)

三、基于注解设定多线程定时任务

一、静态:基于注解

基于注解@Scheduled默认为单线程,开启多个任务时,任务的执行时机会受上一个任务执行时间的影响,通过在配置类注解@EnableScheduling来开启对定时任务的支持,然后在要执行计划任务的方法上注解@Scheduled,声明这是需执行的定时任务

  1. 创建定时器

    使用SpringBoot基于注解来创建定时任务非常简单,只需几行代码就能完成

    @Configuration//主要用于标记配置类,兼备Component的效果
    @EnableScheduling//开启定时任务
    public class StaticScheduleTask{
        //添加定时任务
        @Scheduled(cron="0/5 * * * * ?")
        //或直接指定时间间隔,例如:5秒
        //@Scheduled(fixedRate=5000)
        private void configureTasks(){
            System.err.println("执行静态定时任务时间:"+LocalDateTime.now());
        }
    }
    

    Cron表达式参数分别表示:

    秒(0~59)例如0/5表示每5秒

    分(0~59)

    时(0~23)

    日(0~31)的某天,需计算

    月(0~11)

    周(可填1-7或SUN/MON/TUE/WED/THU/FRI/SAT)

    @Scheduled:除了支持灵活的参数表达式cron之外,还支持简单的延时操作,例如fixedDelay,fixedRate填写相应的毫秒数即可

    cron表达式:依据业务需求,可设定具体的任务执行时间,预定时间一到就会自动执行;
       cron一共有7位,但是最后一位是年,可以留空,一般情况可以写6位:
       * 第一位,表示秒,取值0-59
       * 第二位,表示分,取值0-59
       * 第三位,表示小时,取值0-23
       * 第四位,日期天/日,取值1-31
       * 第五位,日期月份,取值1-12
       * 第六位,星期,取值1-7,星期一,星期二...,注:不是第1周,第二周的意思,另外:1表示星期天,2表示星期一。
       * 第7为,年份,可以留空,取值1970-2099
       
    cron中,还有一些特殊的符号,含义如下:
       (*)星号:可以理解为每的意思,每秒,每分,每天,每月,每年...
       (?)问号:问号只能出现在日期和星期这两个位置。
       (-)减号:表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12
       (,)逗号:表达一个列表值,如在星期字段中使用“1,2,4”,则表示星期一,星期二,星期四
       (/)斜杠:如:x/y,x是开始值,y是步长,比如在第一位(秒) 0/15就是,从0秒开始,每15秒,最后就是0,15,30,45,60    另:*/y,等同于0/y
    
    Cron表达式范例
    	每搁5秒执行一次:*/5 * * * * ?
    	每搁一分钟执行一次:0 */1 * * * ?
    	每天23点执行一次:0 0 23 * * ?
    	每天凌晨1点执行一次:0 0 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 * * ?
    

    缺点:多个定时任务使用同一个调度线程,所以任务是阻塞执行,执行效率低;所有的任务都是在同一线程池中的同一个线程来完成

    优点:使用与单个后台线程执行周期任务,并且保证按照预定时间执行

    但是当我们调整了执行周期的时候,需要重启应用才能生效,这多少有些不方便,为了达到实时生效的效果,可以使用接口来完成定时任务

二、动态:基于接口

​ 实现SchedulingConfigure接口,重写configureTasks方法,添加需执行的定时任务;

  1. 导入依赖包

    <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>2.0.4.RELEASE</version>
        </parent>
    
        <dependencies>
            <dependency><!--添加Web依赖 -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency><!--添加MySql依赖 -->
                 <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency><!--添加Mybatis依赖 配置mybatis的一些初始化的东西-->
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.1</version>
            </dependency>
            <dependency><!-- 添加mybatis依赖 -->
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
                <scope>compile</scope>
            </dependency>
        </dependencies>
    
  2. 添加数据库数据(随便打开查询窗口,执行操作脚本内容),然后在项目中的application.yml添加数据源

    spring
    	datasource:
    	url:jdbc:mysql://localhost:3306/数据库名称
    	username:root
    	password:root
    
  3. 创建定时器

    数据库准备好数据之后,我们编写定时任务,这里添加的是TriggerTask,目的是循环读取我们在数据库设置好的执行周期,以及执行相关定时任务的内容

    @Configuration//主要用于标记配置类,兼备component的效果
    @EnableScheduling//开启定时任务
    public class DynamicScheduleTask implements SchedulingConfigurer{
        @Mapper
        public interface CronMapper{
            @Select("select cron from cron limit 1")
            public String getCron();
        }
        @Autowired//注入mapper
        @SuppressWarnings("all")
        CronMapper cronMapper;
        //执行定时任务
        @Override
        public void configureTasks(ScheduledTask taskRegistrar){
            taskRegistar.addTriggerTask{
                //添加任务内容(Runnable)
                //其中configureTasks()是需要执行的任务
                ()->System.out.println("执行动态定时任务:"+LocalDateTime.now().toLocalTime()),
                //设置执行周期(Trigger)
                triggerContext->{
                    //从数据库获取执行周期
                    String cron=cronMapper.getCron();
                    //合法性校验
                    //cron=0/5 * * * * ?
                    if(StringUtils.isEmpty(cron)){
                        
                    }
                    //返回执行周期(Date)
                    return new CronTrigger(cron).nextExecutiontime(triggerContext);
                }
            }
        }
    }//启动了springboot之后就会发现每次执行的时间差是数据库中设定的定时任务
    

    注意:如果在数据库修改时格式出现错误,则定时任务会停止,即使重新修改正确,此时只能重新启动项目才能恢复

    三、多线程定时任务

    添加@EnableAsync开启对异步的支持

    添加@Async注解,表示该定时任务是异步执行的,如果没有配置线程池的话会默认使用SimpleAsyncTaskExecutor,这个异步执行器每次都会开启一个子线程执行,性能消耗比较大

    //@Component注解用于对那些比较中立的类进行注释
    //相对于在持久层、业务层和控制层分别采用@Repository,@Service和@Controller对分层中的类进行注释
    @Component
    @EnableScheduling//开启定时任务
    @EnableAsync//开启多线程
    public class MultithreadScheduleTask {
        @Async
        @Scheduled(fixedDelay = 1000)//间隔1秒
        public void first() throws InterruptedException{
            System.out.println("第一个定时任务开始:"+ LocalDateTime.now().toLocalTime()+"\r\n线程:"+Thread.currentThread());
            System.out.println();
            Thread.sleep(1000*10);
        }
        @Async
        @Scheduled(fixedDelay = 2000)
        public void second(){
            System.out.println("第二个定时任务开始:"+LocalDateTime.now().toLocalTime()+"\r\n线程:"+Thread.currentThread());
        }
    }
    

参考链接:
https://www.cnblogs.com/mmzs/p/10161936.html
https://blog.csdn.net/qq_41144667/article/details/103795004
https://blog.csdn.net/qq_41144667/article/details/103937193?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2aggregatepagefirst_rank_v2~rank_aggregation-1-103937193.pc_agg_rank_aggregation&utm_term=springboot%E5%9F%BA%E4%BA%8E%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1&spm=1000.2123.3001.4430

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot提供了一种简单易用的方式来实现定时任务,使用了spring-context-support模块中的TaskScheduler和CronSequenceGenerator类。下面是具体的实现步骤: 1.在pom.xml中添加spring-boot-starter-quartz依赖,这个依赖是Quartz的封装,可以方便的实现定时任务。 2.在启动类上添加@EnableScheduling注解,开启定时任务支持。 3.在需要定时执行的方法上添加@Scheduled注解,指定定时任务的执行时间。 4.可以在@Scheduled注解中设置cron表达式,更加灵活的控制任务执行时间。 示例: ```java @SpringBootApplication @EnableScheduling public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Scheduled(fixedRate = 5000) public void reportCurrentTime() { System.out.println("现在时间:" + new Date()); } } ``` 在上面的示例中,@Scheduled(fixedRate = 5000)表示每隔5秒执行一次reportCurrentTime()方法。 如果要使用cron表达式,可以这样写: ```java @Scheduled(cron = "0 0/5 * * * ?") public void reportCurrentTime() { System.out.println("现在时间:" + new Date()); } ``` 这个cron表达式表示每隔5分钟执行一次reportCurrentTime()方法。 除了fixedRate和cron,@Scheduled还支持其他的参数,比如fixedDelay和initialDelay,可以根据自己的需求进行选择。 需要注意的是,定时任务是在一个固定的线程池中执行的,如果任务的执行时间过长,可能会导致线程池满载而无法执行其他任务。因此,要尽量避免任务执行时间过长。 另外,如果需要对定时任务进行动态管理,可以使用Quartz框架,它提供了更加灵活的任务调度功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值