当前位置: 代码网 > it编程>编程语言>Java > SpringBoot最简单的定时任务@Scheduler的使用及解读

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

2025年03月22日 Java 我要评论
springboot定时任务@schedulerspring boot 中一般来说定时任务使用@scheduler注解或者quartz框架,或者自定义线程实现,最简单的当属@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来完成任务的并发.

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com