项目开发中经常需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息。Spring为我们提供了异步执行任务调度的方式,提供TaskExecutor 、TaskScheduler 接口。

SpringBoot中使用两个注解:@EnableScheduling、@Scheduled来简单实现定时任务。

【1】@Scheduled注解

按照惯例,先看javadoc源码:

  • 使一个方法定时被执行的注解。其属性cron/fixedDelay/fixedRate必须有一个被指定

  • 该注解标记的方法没有参数,也没有返回值。即使写了返回值,也会被忽略。

  • 该注解被ScheduledAnnotationBeanPostProcessor处理器解析。

  • 可以手动注册该bean,当然更方便的是使用<task:annotation-driven/>配置或者@EnableScheduling注解。

这个注解可以用来作为一个meta-annotation通过属性覆盖去创建自定义的组合注解。

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {//     cron表达式String cron() default "";//corn表达式的时区,默认为空,使用服务器的local time zone。String zone() default "";//  周期为在最后一次调用结束和下一次调用开始,以毫秒为单位,固定周期地执行注释的方法。long fixedDelay() default -1;//周期间隔为在最后一次调用结束和下一次调用开始,以毫秒为单位,固定周期地执行注释的方法。String fixedDelayString() default "";//固定周期地执行注解方法,周期为调用间隔,单位为毫秒long fixedRate() default -1;String fixedRateString() default "";//  fixedRate() 或fixedDelay()第一次执行前延迟的毫秒数long initialDelay() default -1;//  fixedRate() 或fixedDelay()第一次执行前延迟的毫秒数String initialDelayString() default "";}

【2】@EnableScheduling 注解

启动Spring的定时任务执行能力,通常用在配置类上面,类似于xml片段<task:*>

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {}

该注解会使Spring 容器中所有bean中的@Scheduled注解起作用。如下所示,给定一个类MyTask :

package com.myco.tasks;public class MyTask {// 每1000ms 执行一次该方法@Scheduled(fixedRate=1000)public void work() {// task execution logic}
}

如下配置确保MyTask.work()每1000ms被调用一次。

@Configuration
@EnableScheduling
public class AppConfig {@Beanpublic MyTask task() {return new MyTask();}
}

如果MyTask使用了注解@Component,下面的配置将会确保其@Scheduled标注的方法会被以期望的间隔进行调用。

 @Configuration@EnableScheduling@ComponentScan(basePackages="com.myco.tasks")public class AppConfig {}

甚至可以直接在配置类中写@Scheduled注解标注的方法。

@Configuration
@EnableScheduling
public class AppConfig {*@Scheduled(fixedRate=1000)public void work() {// task execution logic}
}

默认,将会寻找一个相关联的scheduler ,可能是上下文中一个唯一的TaskScheduler或者一个bean id为taskSchedulerScheduledExecutorService也将执行同样的查找。如果上面两个定时任务处理器都没有被找到,一个本地单线程默认scheduler 将会被创建并被注册器使用。

如果想获得更多的控制,配置类应该实现SchedulingConfigurer接口。这将可以获取底层的ScheduledTaskRegistrar实例。

下面的例子演示了如何自定义Executor去执行定时任务。

@Configuration
@EnableScheduling
public class AppConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.setScheduler(taskExecutor());}@Bean(destroyMethod="shutdown")public Executor taskExecutor() {return Executors.newScheduledThreadPool(100);}
}

注意上面例子中@Bean(destroyMethod="shutdown")的使用。这将确保线程任务执行器在Spring容器被销毁时正确的关闭。实现SchedulingConfigurer还可以通过ScheduledTaskRegistrar对任务注册实细粒度的控制。 例如,以下为每个自定义Trigger实现配置特定bean方法的执行

 @Configuration@EnableSchedulingpublic class AppConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.setScheduler(taskScheduler());taskRegistrar.addTriggerTask(new Runnable() {public void run() {myTask().work();}},new CustomTrigger());}@Bean(destroyMethod="shutdown")public Executor taskScheduler() {return Executors.newScheduledThreadPool(42);}@Beanpublic MyTask myTask() {return new MyTask();}}

作为参考,可以将上面的示例与下面的Spring XML配置进行比较

<beans> <task:annotation-driven scheduler="taskScheduler"/><task:scheduler id="taskScheduler" pool-size="42"/><task:scheduled-tasks scheduler="taskScheduler"><task:scheduled ref="myTask" method="work" fixed-rate="1000"/></task:scheduled-tasks><bean id="myTask" class="com.foo.MyTask"/></beans>

更多参考Scheduled、SchedulingConfiguration、SchedulingConfigurer、ScheduledTaskRegistrar、Trigger以及ScheduledAnnotationBeanPostProcessor。

【3】代码实例

Service如下(这里使用cron表达式):

@Service
public class ScheduledService {// 每天的整分调用一次该方法@Scheduled(cron = "0 * * * * 0-7")public void hello(){System.out.println("hello...");}
}

在主程序上添加@EnableScheduling注解如下:

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


fixedRate ,fixedDelay 和initialDelay

代码示例如下:

 //上一次 项目启动时间点之后 5 秒执行一次@Scheduled(fixedRate = 5000)public void fixedRate(){System.out.println("fixedRate: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));}//上一次 结束时间点之后 每50秒执行一次@Scheduled(fixedDelay = 50000)public void fixedDelay(){for (int i = 0; i < 10; i++){System.out.println("fixedDelay" + i  + new SimpleDateFormat("HH:mm:ss").format(new Date()));}}// initialDelay :fixedRate() 或fixedDelay()第一次执行前延迟的毫秒数//第一次延迟50秒执行,之后按照fixedRate的规则每6秒执行一次@Scheduled(initialDelay = 50000,fixedRate = 6000)public void initialDelayFixedRate (){for (int i = 0; i < 10; i++){System.out.println("initialDelayFixedRate :" + i + new SimpleDateFormat("HH:mm:ss").format(new Date()) );}}

【4】cron表达式

cron表达式属性如下:

second(秒), minute(分), hour(时),day of month(日),month(月),day of week(周几)

字段与值表格如下:

字段 允许值 允许的特殊符号
0-59 ,-*/
0-59 ,-*/
小时 0-23 ,-*/
日期 1-31 ,-*?/LWC
月份 1-12 ,-*/
星期 0-7或SUN-SAT 0 7是SUN ,-*?/LC#

特殊符号释义如下:

特殊符号 代表含义
, 枚举
- 区间
* 任意
/ 步长
? 日/星期冲突匹配
L 最后
W 工作日
C 和Calendar联系后计算过的值
# 星期 4#2 第2个星期四

示例如下:

0 0 0 * * * -- 每天零时执行一次
0 0/15 14,18 * * ? -- 每天14点整和18点整,每隔15分钟执行一次
0 15 10 ? * 1-6 -- 每个月的周一到周六 10:15分执行一次
0 0 2 ? * 6L -- 每个月的最后一个周六凌晨2点执行一次
0 0 2 LW * ? -- 每个月的最后一个工作日凌晨2点执行一次
0 0 2-4 ? * 1#1 -- 每个月的第一个周一凌晨2点到4点期间,每个整点都执行一次

实现定时任务的方式很多,其他的有JDK 自带的 TimerTask or Timer、使用开源作业调度框架 Quartz、线程池 ScheduleExecutorService 和其实现类ScheduledThreadPoolExecutor

参考博文:多线程并发之Executor。

SpringBoot - 定时任务入门(@Scheduled )详解相关推荐

  1. SpringBoot 定时任务cron表达式详解

    cron表达式 顺序 秒 分钟 小时 日期 月份 星期 年(可选) 取值 0-59 0-59 0-23 1-30(31) 1-12 1-7允许特殊字符 , - * / , - * / , - * / ...

  2. python 快速排序_小白入门知识详解:Python实现快速排序的方法(含实例代码)...

    前言: 今天为大家带来的内容是:小白入门知识详解:Python实现快速排序的方法(含实例代码)希望通过本文的内容能够对各位有所帮助,喜欢的话记得点赞转发收藏不迷路哦!!! 提示: 这篇文章主要介绍了P ...

  3. [老男孩笔记系列]-之linux定时任务crontab命令详解

    linux定时任务crontab命令详解 1.1指令语法 crontab [ -u user ] file crontab [ -u user ] { -l | -r | -e } 1.2指令说明 通 ...

  4. Springboot@Configuration和@Bean详解

    Springboot@Configuration和@Bean详解 一.@Configuration @Target({ElementType.TYPE}) @Retention(RetentionPo ...

  5. java定时任务框架elasticjob详解

    这篇文章主要介绍了java定时任务框架elasticjob详解,Elastic-Job是ddframe中dd-job的作业模块中分离出来的分布式弹性作业框架.该项目基于成熟的开源产品Quartz和Zo ...

  6. python定时任务crontab_【Python】Linux crontab定时任务配置方法(详解)

    CRONTAB概念/介绍 crontab命令用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于"crontab"文件中,以供之后读取和执行. cron 系统调度 ...

  7. SpringBoot (6)---RestTemplate方法详解(2)

    SpringBoot (6)---RestTemplate方法详解(2) 说明 上一篇SpringBoot 2.1 | 第三篇:RestTemplate请求HTTP(1)简单运用了RestTempla ...

  8. python入门教程pdf-Python入门教程详解.pdf

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp计算机&nbsp>&nbspPython Python入门教程详解.pdf132页 本文档一 ...

  9. Springboot多数据源配置详解

    Springboot多数据源配置详解 概念 配置 多数据源使用 概念 一般来说,我们正常的业务只涉及一个数据源,在特定的业务场景中需要使用多个数据源的情况,就需要配置多个数据源来满足特定的业务需求.本 ...

最新文章

  1. 兼容ie9以下css3,hover和圆角(htc)
  2. 用Arduino检测环境中的温湿度
  3. 密码学AES算法_S盒_C值搜索
  4. 『数据库』无聊到爆炸的数据库文章--数据库的安全性
  5. Rabbits —— HDU-6227
  6. cad 打开硬件加速卡_CAD卡顿?电脑带不动?几个简单实用的方法,解决CAD运行卡顿问题...
  7. 迈足狂奔!铁塔公司:目前北京已建好4400多座大型5G基站
  8. java里面怎么添加表约束_alter table添加表约束
  9. 技术再好,能阻止暴力视频的疯传吗?
  10. GeekOS课程设计-project1
  11. 素数筛法求素数(线性时间)
  12. 非标机械设计该怎么做,老机械工程师告诉你
  13. 网络协议篇之CWMP协议(二)—— CWMP(TR-069)业务流程
  14. 《QTreeView表项实现排序的2种方式》:系列教程之九
  15. 老调重谈:C语言中的指针和数组
  16. 小米手机线刷USB3.0的问题
  17. 1.请求和响应(phalapi框架总结)
  18. C# 自定义动态九宫格键盘,简单实用
  19. 小白尝试——去除apk流氓权限
  20. OpenCL学习笔记一

热门文章

  1. 收藏关于wifi技术论坛
  2. (操作系统)生产者消费者问题
  3. QT为pushButton添加下拉菜单,并添加信号槽
  4. 使用雅虎邮箱的几大收获
  5. Lotus防病毒与数据备份案例
  6. [英语,iOS]美式英语语音语调基础
  7. mysql general error,mysql General error: 1267 Illegal mix of collations错误​
  8. C语言练习题:企业发放的奖金根据利润提成。利润 I 低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成
  9. GB28181 实时视频点播流程
  10. 【论文阅读】SIGIR 2021:Hierarchical Multi-modal Contextual Attention Network for Fake News Detection