序言

Spring 3.0 版本之后自带定时任务,提供了@EnableScheduling注解和@Scheduled注解来实现定时任务功能。

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

  • 1、基于注解(@Scheduled)
  • 2、基于接口(SchedulingConfigurer) 前者相信大家都很熟悉,但是实际使用中我们往往想从数据库中读取指定时间来动态执行定时任务,这时候基于接口的定时任务就派上用场了。
  • 3、基于注解设定多线程定时任务

1、基于注解(@Scheduled)

1.1 @Scheduled注解和@EnableScheduling注解的使用

基于注解@Scheduled默认为单线程,开启多个任务时,任务的执行时机会受上一个任务执行时间的影响。

@EnableScheduling注解: 在配置类上使用,开启计划任务的支持(类上)。

@Scheduled注解: 来声明这是一个任务,包括 cron,fixDelay,fixRate 等类型(方法上,需先开启计划任务的支持)。

【示例】SpringBoot项目中使用@Scheduled注解和@EnableScheduling注解实现定时任务。

(1)开启定时任务

SpringBoot 项目在项目启动类上添加 @EnableScheduling 注解即可开启定时任务管理。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;@SpringBootApplication
@EnableScheduling //开启定时任务
public class ScheduledDemoApplication
{public static void main(String[] args){SpringApplication.run(ScheduledDemoApplication.class, args);}
}

(2)创建定时任务

创建定时任务,并使用 @Scheduled 注解。

package com.pjb.Schedule;import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.text.SimpleDateFormat;
import java.util.Date;/*** 定时任务的使用* @author pan_junbiao**/
@Component
public class Task
{@Scheduled(cron="0/5 * *  * * ? ")   //每5秒执行一次public void execute(){SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //设置日期格式System.out.println("欢迎访问 pan_junbiao的博客 " + df.format(new Date()));}
}

执行结果:

1.2 @Scheduled注解各参数讲解

@Scheduled注解的使用这里不详细说明,直接对8个参数进行讲解。

@Scheduled注解类的源码如下:

package org.springframework.scheduling.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {String CRON_DISABLED = "-";String cron() default "";String zone() default "";long fixedDelay() default -1L;String fixedDelayString() default "";long fixedRate() default -1L;String fixedRateString() default "";long initialDelay() default -1L;String initialDelayString() default "";
}

1.2.1 cron

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

cron 表达式语法:

格式:[秒] [分] [小时] [日] [月] [周] [年]

序号 说明 是否必填 允许填写的值 允许的通配符
1 0-59 , - * /
2 0-59 , - * /
3 小时 0-23 , - * /
4 1-31 , - * ? / L W
5 1-12 or JAN-DEC , - * /
6 1-7 or SUN-SAT , - * ? / L #
7 empty 或 1970-2099 , - * /

通配符说明:

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

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

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

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

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

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

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

小提示:'L'和 'W'可以一组合使用。如果在日字段上设置"LW",则表示在本月的最后一个工作日触发(一般指发工资) 。

# 序号(表示每月的第几个周几),例如在周字段上设置"6#3"表示在每月的第三个周六.注意如果指定"#5",正好第五周没有周六,则不会触发该配置(用在母亲节和父亲节再合适不过了)

小提示:周字段的设置,若使用英文字母是不区分大小写的 MON 与mon相同。

可通过在线生成Cron表达式的工具:http://cron.qqe2.com/ 来生成自己想要的表达式。

常用示例:

0 0 12 * * ? 每天12点触发
0 15 10 ? * * 每天10点15分触发
0 15 10 * * ? 每天10点15分触发
0 15 10 * * ? * 每天10点15分触发
0 15 10 * * ? 2005 2005年每天10点15分触发
0 * 14 * * ? 每天下午的 2点到2点59分每分触发
0 0/5 14 * * ? 每天下午的 2点到2点59分(整点开始,每隔5分触发)
0 0/5 14,18 * * ? 每天下午的 2点到2点59分(整点开始,每隔5分触发)每天下午的 18点到18点59分(整点开始,每隔5分触发)
0 0-5 14 * * ? 每天下午的 2点到2点05分每分触发
0 10,44 14 ? 3 WED 3月分每周三下午的 2点10分和2点44分触发
0 15 10 ? * MON-FRI 从周一到周五每天上午的10点15分触发
0 15 10 15 * ? 每月15号上午10点15分触发
0 15 10 L * ? 每月最后一天的10点15分触发
0 15 10 ? * 6L 每月最后一周的星期五的10点15分触发
0 15 10 ? * 6L 2002-2005 从2002年到2005年每月最后一周的星期五的10点15分触发
0 15 10 ? * 6#3 每月的第三周的星期五开始触发
0 0 12 1/5 * ? 每月的第一个中午开始每隔5天触发一次
0 11 11 11 11 ? 每年的11月11号 11点11分触发(光棍节)

cron表达式使用占位符

另外,cron属性接收的cron表达式支持占位符。eg:

配置文件:

time:cron: */5 * * * * *interval: 5

每5秒执行一次:

@Scheduled(cron="${time.cron}")
void testPlaceholder1() {System.out.println("Execute at " + System.currentTimeMillis());
}@Scheduled(cron="*/${time.interval} * * * * *")
void testPlaceholder2() {System.out.println("Execute at " + System.currentTimeMillis());
}

1.2.2 zone

时区,接收一个 java.util.TimeZone#ID。cron表达式会基于该时区解析。默认是一个空字符串,即取服务器所在地的时区。比如我们一般使用的时区Asia/Shanghai。该字段我们一般留空。

1.2.3 fixedDelay

上一次执行完毕时间点之后多长时间再执行。如:

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

1.2.4 fixedDelayString

与 1.2.3 fixedDelay 意思相同,只是使用字符串的形式。唯一不同的是支持占位符。如:

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

占位符的使用:

在 application.yml 配置文件中添加如下配置:

time:fixedDelay: 5000

编写相关代码:

/*** 定时任务的使用* @author pan_junbiao**/
@Component
public class Task
{@Scheduled(fixedDelayString = "${time.fixedDelay}")void testFixedDelayString(){System.out.println("欢迎访问 pan_junbiao的博客 " + System.currentTimeMillis());}
}

执行结果:

1.2.5 fixedRate

上一次开始执行时间点之后多长时间再执行。如:

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

1.2.6 fixedRateString

与 1.2.5 fixedRate 意思相同,只是使用字符串的形式。唯一不同的是支持占位符。

1.2.7 initialDelay

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

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

1.2.8 initialDelayString

与 1.2.7 initialDelay 意思相同,只是使用字符串的形式。唯一不同的是支持占位符。

2、动态:基于接口(SchedulingConfigurer)

基于接口(SchedulingConfigurer)。

(1)创建数据表

在MySQL数据库中创建 cron 表,并添加数据。

DROP TABLE IF EXISTS cron;
CREATE TABLE cron  (cron_id VARCHAR(30) NOT NULL PRIMARY KEY,cron VARCHAR(30) NOT NULL
);INSERT INTO cron VALUES ('1', '0/5 * * * * ?');

(2)添加pom.xml配置信息

在pom.xml配置文件中添加MyBatis、 MySQL的JDBC数据库驱动依赖。

<!-- MyBatis与SpringBoot整合依赖 -->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.3</version>
</dependency><!-- MySQL的JDBC数据库驱动 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.20</version>
</dependency>

(3)配置相关信息

将项目默认的application.properties文件的后缀修改为“.yml”,即配置文件名称为:application.yml,并配置以下信息:

spring:#DataSource数据源datasource:url: jdbc:mysql://localhost:3306/db_admin?useSSL=false&ampusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver#MyBatis配置
mybatis:type-aliases-package: com.pjb.entity #别名定义configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #指定 MyBatis 所用日志的具体实现,未指定时将自动查找map-underscore-to-camel-case: true #开启自动驼峰命名规则(camel case)映射lazy-loading-enabled: true #开启延时加载开关aggressive-lazy-loading: false #将积极加载改为消极加载(即按需加载),默认值就是falselazy-load-trigger-methods: "" #阻挡不相干的操作触发,实现懒加载cache-enabled: true #打开全局缓存开关(二级环境),默认值就是true

(4)创建定时器

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

package com.pjb.config;import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.StringUtils;import java.time.LocalDateTime;/*** 动态定时任务配置类* @author pan_junbiao**/
@Configuration      //1.主要用于标记配置类,兼备Component的效果
@EnableScheduling   //2.开启定时任务
public class DynamicScheduleConfigurer implements SchedulingConfigurer
{@Mapperpublic interface CronMapper {@Select("select cron from cron limit 1")public String getCron();}//注入mapper@Autowired@SuppressWarnings("all")CronMapper cronMapper;/*** 执行定时任务.*/@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar){taskRegistrar.addTriggerTask(//1.添加任务内容(Runnable)() -> System.out.println("欢迎访问 pan_junbiao的博客: " + LocalDateTime.now().toLocalTime()),//2.设置执行周期(Trigger)triggerContext -> {//2.1 从数据库获取执行周期String cron = cronMapper.getCron();//2.2 合法性校验.if (StringUtils.isEmpty(cron)) {// Omitted Code ..}//2.3 返回执行周期(Date)return new CronTrigger(cron).nextExecutionTime(triggerContext);});}
}

执行结果:

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

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

创建多线程定时任务。

package com.pjb.Task;import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;/*** 基于注解设定多线程定时任务* @author pan_junbiao*/
@Component
@EnableScheduling   // 1.开启定时任务
@EnableAsync        // 2.开启多线程
public class MultithreadScheduleTask
{@Async@Scheduled(fixedDelay = 1000)  //间隔1秒public void first() throws InterruptedException {System.out.println("第一个定时任务开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName());System.out.println();Thread.sleep(1000 * 10);}@Async@Scheduled(fixedDelay = 2000)public void second() {System.out.println("第二个定时任务开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName());System.out.println();}
}

注意:由于基于注解@Scheduled默认为单线程,开启多个任务时,任务的执行时机会受上一个任务执行时间的影响。所以这里使用 @Async 注解很关键。

执行结果:

从控制台可以看出,第一个定时任务和第二个定时任务互不影响;

并且,由于开启了多线程,第一个任务的执行时间也不受其本身执行时间的限制,所以需要注意可能会出现重复操作导致数据异常。

学习资料1:https://blog.csdn.net/MobiusStrip/article/details/85126261

学习资料2:https://www.jianshu.com/p/1defb0f22ed1

原文地址:https://blog.csdn.net/pan_junbiao/article/details/109399280

SpringBoot使用@Scheduled注解实现定时任务相关推荐

  1. java定时任务_java:springBoot使用@Scheduled注解配置定时任务

    定时任务的实现有多种,其中一种就是使用Spring提供的注解: @Schedule . 下面举个简单的例子 1.先在springboot的入口处添加@EnableScheduling这个注解 2.总开 ...

  2. Spring的@Scheduled注解实现定时任务

    Spring的@Scheduled注解实现定时任务 [简介篇] 项目经常会用到定时任务,实现定时任务的方式有很多种.在Spring框架中,实现定时任务很简单,常用的实现方式是使用注解@Schedule ...

  3. Spring 的@Scheduled注解实现定时任务运行和调度

    Spring 的@Scheduled注解实现定时任务运行和调度 首先要配置我们的spring.xml   ---  即spring的主配置文件(有的项目中叫做applicationContext.xm ...

  4. scheduled每天下午1点执行一次_在Spring Boot项目中使用@Scheduled注解实现定时任务...

    在java开发中定时任务的实现有多种方式,jdk有自己的定时任务实现方式,很多框架也有定时任务的实现方式.这里,我介绍一种很简单的实现方式,在Spring Boot项目中使用两个注解即可实现. 在sp ...

  5. java @Scheduled注解执行定时任务

    使用spring @Scheduled注解执行定时任务: @Scheduled(cron = "0 0 2 * * ?") //每天凌晨2点@RequestMapping(&quo ...

  6. scheduled java_java使用@Scheduled注解执行定时任务

    前言 在写项目的时候经常需要特定的时间做一些特定的操作,尤其是游戏服务器,维护线程之类的,这时候就需要用到定时器. 如果此时你刚好用的是spring的话,哪么@scheduled注解是非常好用的. 使 ...

  7. @Scheduled注解实现定时任务

    @Scheduled注解实现定时任务 开启定时任务 配置定时任务 cron 表达式格式 通配符含义 开启定时任务 使用 @Scheduled 非常容易,直接创建一个 Spring Boot 项目,并且 ...

  8. java scheduled_怎么在java中利用@Scheduled注解执行定时任务

    怎么在java中利用@Scheduled注解执行定时任务 发布时间:2021-01-13 16:52:56 来源:亿速云 阅读:84 作者:Leah 本篇文章给大家分享的是有关怎么在java中利用@S ...

  9. 定时任务——@Scheduled注解做定时任务

    一.这是springboot中配置静态定时任务的注解 1. 在启动类上面加上 @EnableScheduling 注解开启定时任务 import org.springframework.boot.Sp ...

最新文章

  1. brave浏览器_Brave for Mac(安全浏览器)
  2. 软件测试有没有测试大纲文档,系统测试大纲(范例).docx
  3. Exceptionless 本地部署
  4. 电脑显示链接网络正常但是不能上网,用某些软件会提示系统丢失libeay32.dll
  5. .net pdf转图片_PDF转图片怎么做?PDF一键转图片!
  6. SVG(可扩展矢量图)系列教程
  7. SQLServer批量倒入目录文件
  8. jtoken判断是否包含键_Redis源码解析十三--有序集合类型键实现(t_zset)
  9. java题库app有什么,Java面试题库
  10. PASCAL VOC数据集简介
  11. MongoDB管理工具studio 3t ,解决到期问题
  12. 技嘉 B85-HD3 4590 OC 引导文件 基本完美
  13. matlab简单几何图形的识别代码,MATLAB识别几何图形
  14. 软件开发中的时区问题
  15. 12.10.3 冻结窗格
  16. PPT如何锁定一些元素(使用母版的策略)
  17. 西门子s7-200PLC编程软件
  18. 01.使用微软官方工具制作启动U盘--非常推荐
  19. 透视映客半年报:亏损背后的长期价值
  20. java实现socket通讯

热门文章

  1. 如何设置excel数值为0不显示
  2. TL-WR842无线桥接(WDS)方法及案例
  3. tlwr845n服务器未响应,联普TL-WR845N路由器WDS桥接如何设置
  4. goodcrawler的使用说明
  5. 【全志T113-S3_100ask】16-1 linux系统驱动四线电阻屏(tpadc、tslib)
  6. 西工大计算机技术研究生就业质量,西北工业大学2019届毕业生就业质量年度报告...
  7. nginx File not found 错误(Nginx无法解析PHP文件)
  8. python语言字符串定义_Python语言基础1-字符串
  9. react-navigation 返回刷新
  10. 中国牛人自制直升机,视频 仅花2万RMB