咱们在编写 Spring Boot 利用中常常会遇到这样的场景,比方:我须要定时地发送一些短信、邮件之类的操作,也可能会定时地检查和监控一些标记、参数等。
创立定时工作
在 Spring Boot 中编写定时工作是非常简单的事,上面通过实例介绍如何在 Spring Boot 中创立定时工作,实现每过 5 秒输入一下以后工夫。
- 在 Spring Boot 的主类中退出
@EnableScheduling
注解,启用定时工作的配置
@SpringBootApplication
@EnableScheduling
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);
}
}
- 创立定时工作实现类
@Component
public class ScheduledTasks {private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
@Scheduled(fixedRate = 5000)
public void reportCurrentTime() {log.info("当初工夫:" + dateFormat.format(new Date()));
}
}
- 运行程序,控制台中能够看到相似如下输入,定时工作开始失常运作了。
2021-07-13 14:56:56.413 INFO 34836 --- [main] c.d.chapter71.Chapter71Application : Started Chapter71Application in 1.457 seconds (JVM running for 1.835)
2021-07-13 14:57:01.411 INFO 34836 --- [scheduling-1] com.didispace.chapter71.ScheduledTasks : 当初工夫:14:57:01
2021-07-13 14:57:06.412 INFO 34836 --- [scheduling-1] com.didispace.chapter71.ScheduledTasks : 当初工夫:14:57:06
2021-07-13 14:57:11.413 INFO 34836 --- [scheduling-1] com.didispace.chapter71.ScheduledTasks : 当初工夫:14:57:11
2021-07-13 14:57:16.413 INFO 34836 --- [scheduling-1] com.didispace.chapter71.ScheduledTasks : 当初工夫:14:57:16
@Scheduled
详解
在下面的入门例子中,应用了 @Scheduled(fixedRate = 5000)
注解来定义每过 5 秒执行的工作。对于@Scheduled
的应用,咱们从源码里看看有哪些配置:
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
String CRON_DISABLED = ScheduledTaskRegistrar.CRON_DISABLED;
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 "";}
这些具体配置信息的含意如下:
- cron:通过 cron 表达式来配置执行规定
- zone:cron 表达式解析时应用的时区
- fixedDelay:上一次执行完结到下一次执行开始的间隔时间(单位:ms)
- fixedDelayString:上一次工作执行完结到下一次执行开始的间隔时间,应用 java.time.Duration#parse 解析
- fixedRate:以固定距离执行工作,即上一次工作执行开始到下一次执行开始的间隔时间(单位:ms),若在调度工作执行时,上一次工作还未执行结束,会退出 worker 队列,期待上一次执行实现后立刻执行下一次工作
- fixedRateString:与 fixedRate 逻辑统一, 只是应用 java.time.Duration#parse 解析
- initialDelay:首次工作执行的延迟时间
- initialDelayString:首次工作执行的延迟时间, 应用 java.time.Duration#parse 解析
思考与进阶
是不是这样实现定时工作很简略呢?那么持续思考一下这种实现形式是否存在什么弊病呢?
可能初学者不太容易发现问题,但如果你曾经有肯定的线上我的项目教训的话,问题也是不言而喻的:这种模式实现的定时工作短少在集群环境下的协调机制。
什么意思呢?假如,咱们要实现一个定时工作,用来每天网上统计某个数据而后累加到原始数据上。咱们开发测试的时候不会有问题,因为都是单过程在运行的。然而,当咱们把这样的定时工作部署到生产环境时,为了更高的可用性,启动多个实例是必须的。此时,工夫一到,所有启动的实例就会同时开始执行这个工作。那么问题也就呈现了,因为有累加操作,最终咱们的后果就会呈现问题。
解决这样问题的形式很多种,比拟通用的就是采纳分布式锁的形式,让同类工作之前的时候以分布式锁的形式来管制执行程序,比方:应用 Redis、Zookeeper 等具备分布式锁性能的中间件配合就能很好的帮忙咱们来协调这类工作在集群模式下的执行规定。
除此之外,那么你还有什么好办法来解决吗?留言说说你的认识吧!不要走开,本系列教程《Spring Boot 2.x 基础教程》继续更新中哦!。学习过程中如遇艰难,倡议退出 Spring 技术交换群,参加交换与探讨,更好的学习与提高!
代码示例
本文的残缺工程能够查看上面仓库中的 chapter7-1
目录:
- Github:https://github.com/dyc87112/SpringBoot-Learning/
- Gitee:https://gitee.com/didispace/SpringBoot-Learning/
** 如果您感觉本文不错,欢送 Star
反对,您的关注是我保持的能源!
欢送关注我的公众号:程序猿 DD,分享其余中央看不到的常识与思考