springboot使用定时任务

  1. 定时任务是企业级开发中必不可少的组成部分,下面这些都离不开定时任务:
    • 长周期业务数据的计算
    • 年度报表
    • 系统脏数据的处理
    • 系统性能监控报告
    • 抢购类活动的商品上架

java中做定时任务的api

java 复制代码
public class TimerTaskApp {
    public static void main(String[] args) {
    //  创建一个定时器对象
        Timer timer = new Timer();
        // task是一个具体要完成的定时任务对象(即要做什么)
        TimerTask task = new TimerTask() {
            @Override
            public void run() {  //多线程
            //这里定义你定时要做的事情
                System.out.println("timer task run...");
            }
        };
        // schedule(定时任务对象,定时任务的开始时间,多久运行一次)
        timer.schedule(task,0,2000);
    }
}

Quartz

  1. Quartz技术是一个比较成熟的定时任务框架,Quartz用起来比较麻烦,配置相对较繁琐。
  2. Quarz的概念:
    • 工作(Job):用于定义具体执行的工作
    • 工作明细(JobDetail):用于描述定时工作相关的信息
    • 触发器(Trigger):描述了工作明细与调度器的对应关系
    • 调度器(Scheduler):用于描述触发工作的执行规则,通常使用cron表达式定义规则

简单说就是你定时干什么事情,这就是工作,工作不可能就是一个简单的方法,还要设置一些明细信息。工作啥时候执行,设置一个调度器,可以简单理解成设置一个工作执行的时间。工作和调度都是独立定义的,它们两个怎么配合到一起呢?用触发器

cron表达式

  1. 格式:{秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空,spring不可以用此字段)}

    ("0/5 * * * * ?"):表示从每分钟的0秒开始,每隔5秒触发一次。

  2. cron 中的通配符的认识:

    (1)* :表示匹配该域的任意值。(* * * * * ?) ,每分每秒都在触发

    (2)? :表示不指定值,只能用在[日]和[周]两个域。一般指定了日期就不用指定周了,或者指定了周几就不用指定日期:("1 * * * * ?"):表示每分钟的第一秒触发

    (3)- :表示该域的连续范围。("5-10 * * * * ?"):表示在每分钟的5秒到10秒之间,每秒触发一次。

    (4)/ :该符号将所在域中的表达式分为两个部分,第一部分表示起始时间,第一部分表示间隔时间。("0/1 * * * * ?"):表示从每分钟的第0秒开始,每隔1秒执行一次。这里的0就表示起始时间,1就表示间隔时间

    (5), :表示匹配该域的指定值。("* 1,2,3 * * * ?")则表示分别在第1 分、第 2分、 第3分的每秒时间都执行该定时任务。

    (6)L :表示表示英文中的last 的意思,只能出现在[日] 和 [周]域。如果在"L"前加上数字,则表示该数据的最后一个。例如在[周]域使用5L,意味着在最后的一个星期四触发。 ([周]域里面1表示周日,2表示周一,以此类推,7表示周六)

    (7)W :表示有效工作日 (周一到周五),只能出现在[日]域且只能用在具体的数字之后,系统将在离指定日期最近的有效工作日触发定时任务。例如在[日]域使用5W,如果5号在星期一到星期五中的一天,则就在5号触发;如果5号是星期六,则将在最近的工作日:星期五,即4号触发;如果5号是星期天,则在6号(周一)触发。另外一点,W的最近寻找不会跨过月份 。例如 1号是星期六,"1W" 就只能往本月的下一个最近的工作日推不能跨月往上一个月推。

    (8)LW :这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五

    (9)# :用于确定每个月第几个周几,只能出现在[周]域。例如"2#3" 表示在每月的第三个周一。([周]域里面1表示周日,2表示周一,以此类推,7表示周六)

  3. cron表达式生成器地址

springboot整合Quarz

  1. 步骤①:导入springboot整合Quartz的starter
xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
  1. 步骤②:定义任务Bean(这里不是定义成spring管理的bean),按照Quartz的开发规范制作,需要继承QuartzJobBean
java 复制代码
public class MyQuartz extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
//        context是工作执行的上下文对象
//        方法里面定义具体要做的事情
        System.out.println("quartz task run...");
    }
}
  1. 步骤③:创建Quartz配置类,定义工作明细(JobDetail)与触发器的(Trigger)bean
java 复制代码
//配置类
@Configuration
public class QuartzConfig {

	// 工作明细:
// 	工作明细中要设置对应的具体工作,使用newJob()操作传入对应的工作任务类型即可。
    @Bean
    public JobDetail printJobDetail(){
        //绑定具体的工作(具体要做什么),
        // MyQuartz.class:定义指定的工作种类
        // storeDurably()用来做持久化的,如果没有使用,会帮你自动存储
        return JobBuilder.newJob(MyQuartz.class).storeDurably().build();
    }
    
	// 触发器
    @Bean
    public Trigger printJobTrigger(){
    // 使用cron表达式,用来描述任务的执行时间(秒 分 时 日 月 星期)
        ScheduleBuilder schedBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
        //绑定对应的工作明细
        return TriggerBuilder.newTrigger().forJob(printJobDetail()).withSchedule(schedBuilder).build();
    }
}

触发器需要绑定任务,使用forJob()操作传入绑定的工作明细对象。此处可以为工作明细设置名称然后使用名称绑定,也可以直接调用对应方法绑定。触发器中最核心的规则是执行时间,此处使用调度器定义执行时间,执行时间描述方式使用的是cron表达式。有关cron表达式的规则,各位小伙伴可以去参看相关课程学习,略微复杂,而且格式不能乱设置,不是写个格式就能用的,写不好就会出现冲突问题。

  1. 总结
    *
    1. springboot整合Quartz就是将Quartz对应的核心对象交给spring容器管理,包含两个对象,JobDetail和Trigger对象
      1. JobDetail对象描述的是工作的执行信息,需要绑定一个QuartzJobBean类型的对象
      1. Trigger对象定义了一个触发器,需要为其指定绑定的JobDetail是哪个,同时要设置执行周期调度器

springboot使用Task

  1. spring根据定时任务的特征,将定时任务的开发简化到了极致。

    • 第一步:在引导类中添加@EnableScheduling,开启定时任务功能;
    • 第二步:定义Bean,在对应要定时执行的操作上方,使用注解**@Scheduled定义执行的时间**,执行时间的描述方式还是cron表达式
  2. 步骤①:开启定时任务功能,在引导类上开启定时任务功能的开关,使用注解@EnableScheduling

java 复制代码
@SpringBootApplication
//开启定时任务功能
@EnableScheduling
public class TaskApplication {

    public static void main(String[] args) {
        SpringApplication.run(TaskApplication.class,args);
    }
}
  1. 步骤②:定义Bean,在对应要定时执行的操作上方,使用注解@Scheduled定义执行的时间,执行时间的描述方式还是cron表达式
java 复制代码
@Component
public class MyBean {
    @Scheduled(cron = "0/1 * * * * ?")
    public void print(){
        System.out.println(Thread.currentThread().getName()+" :spring task run...");
    }
}

这就完成了定时任务的配置。总体感觉其实什么东西都没少,只不过没有将所有的信息都抽取成bean,而是直接使用注解绑定定时执行任务的事情而已。

  1. 如何想对定时任务进行相关配置,可以通过配置文件进行
yaml 复制代码
spring:
  task:
   	scheduling:
      pool:
       	size: 1							# 任务调度线程池大小 默认 1
      thread-name-prefix: ssm_      	# 调度线程名称前缀 默认 scheduling-      
        shutdown:
          await-termination: false		# 线程池关闭时 是否 等待所有任务完成
          await-termination-period: 10s	# 调度线程关闭前 最大等待时间,确保最后一定关闭
  1. 总结
    *
    1. spring task需要使用注解@EnableScheduling开启定时任务功能
      1. 为定时执行的的任务设置执行周期,描述方式cron表达式
      1. Spring Task 基于 @Scheduled 的定时任务调度,不支持集群,虽然可以通过分布式锁保证任务执行时的互斥,但是不能动态感知任务异常中断的情况。
相关推荐
一只叫煤球的猫2 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
bobz9653 小时前
tcp/ip 中的多路复用
后端
bobz9653 小时前
tls ingress 简单记录
后端
皮皮林5514 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
你的人类朋友4 小时前
什么是OpenSSL
后端·安全·程序员
bobz9654 小时前
mcp 直接操作浏览器
后端
前端小张同学7 小时前
服务器部署 gitlab 占用空间太大怎么办,优化思路。
后端
databook7 小时前
Manim实现闪光轨迹特效
后端·python·动效
武子康8 小时前
大数据-98 Spark 从 DStream 到 Structured Streaming:Spark 实时计算的演进
大数据·后端·spark
该用户已不存在8 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net