重写 Spring Boot 定时任务,支持可动态调整执行时间 - 今日头条

本文由 简悦 SimpRead 转码, 原文地址 www.toutiao.com

Spring Boot 应该是目前最火的 java 开源框架了,它简化了我们创建一个 web 服务的过程,让我们可以在很短时间、基本零配置就可以启动一个 w

Spring Boot 应该是目前最火的 java 开源框架了,它简化了我们创建一个 web 服务的过程,让我们可以在很短时间、基本零配置就可以启动一个 web 服务。

定时任务在我们平常的业务开发用的非常多,Spring Boot 创建一个定时任务很简单,只需要用 @Scheduled 注解方法,就可以让方法按照定义的时间进行运行。但是,Spring Boot 的 @Scheduled 默认是单线程的,也就是如果有两个定时任务,那第二个定时必须在第一个定时任务执行完成之后才能开始执行。当然我们可以使用 @Async 让方法异步,来达到多线程的目的。但是,今天我要讲的是如何重写 Spring Boot 定时任务,并可支持动态调整执行时间。

https://p9.toutiaoimg.com/origin/pgc-image/299d791bfc664157a61aa25cc6312ae7?from=pc

实例代码中我们定义了两个需要进行定时触发的任务。并且自定义注解 @CronScheduled

自定义注解的作用主要在于后续的逻辑可以获取到该方法的执行周期。同时也可以定义其它的属性,用于后续的业务逻辑处理

https://p9.toutiaoimg.com/origin/pgc-image/5fdf23d6d8e846beb6bb9d5d42b40b26?from=pc

标题我们提出了支持可动态调整执行时间。平常的定时任务中我们没法动态调整执行时间,除非重启应用。那我们咋这里怎么动态调整时间呢?思路是:重新注册任务。当我们检测到定时任务的执行时间发生变化,我们就重新注册任务。如果我们的定时任务表达式是配置在数据库,那我们可以定时轮训数据库获取,检测到变化了就重新注册。如果是配置在配种中心,配置中心一般会有触发器 trigger。当我们接受配置中心数据发生变化的通知以后,我们重新注册定时任务。

https://p9.toutiaoimg.com/origin/pgc-image/87daf9e553c74254a29802320b2da9e2?from=pc

重新注册任务的方法

https://p9.toutiaoimg.com/origin/pgc-image/03bc6e3230644e779fc9d8670913e6e3?from=pc

reReqiester 方法可以暴露出去被其它类调用。当外部逻辑检测到定时任务的执行时间发生变化,调用此方法重新注册定时任务

ScheduledTaskRegistrar 是 Task 的一个容器, 内部维护了这些 Task List 和 executor 的引用, 并负责将 Task 置入 executor 中执行。ScheduledTaskRegistrar 的实现原理大家自行研究。这里就不进行详细解释。

实现 BeanPostProcessor 可以在 ScheduleTask 对象实例化以后,我们调用自己的逻辑方法。在这里我们用来触发 configureTasks 方法。

https://p9.toutiaoimg.com/origin/pgc-image/660d00458b4b4bd595b0814bdc0a72c6?from=pc

至此,我们就自己实现了定时任务的调度,在调度的过程中,我们也可以加入自己逻辑处理业务。