Spring6.x对调度和异步执行的注解支持

Spring为任务调度和异步方法执行提供注解支持。

1 启用Scheduling注解

要启用 @Scheduled@Async ,在 @Configuration 类(或者在启动类)添加 @EnableScheduling@EnableAsync,如下:

java 复制代码
@Configuration
@EnableAsync
@EnableScheduling
public class AppConfig {

}
java 复制代码
@SpringBootApplication(exclude = {
		DataSourceAutoConfiguration.class,
})
@EnableScheduling
public class RoadSyncApplication {

	public static void main(String[] args) {
		SpringApplication.run(RoadSyncApplication.class, args);
	}
}

你可以为你的应用程序选择相关的注解。例如,如果你只需要支持 @Scheduled,可以省略 @EnableAsync。对于更细粒度的控制,你还可以分别实现 SchedulingConfigurer 接口和 AsyncConfigurer 接口。有关完整详细信息,请参阅 SchedulingConfigurerAsyncConfigurer javadoc。

默认处理 @Async 注解的建议模式是 proxy,它仅允许通过代理拦截调用。使用这种方式无法拦截同一类中的本地调用。 对于更高级的拦截模式,请考虑切换到 aspectj 模式与编译时织入或加载时织入结合使用。

2 @Scheduled 注解

可将 @Scheduled 注解以及触发元数据添加到方法中。

2.1 fixedDelay

如下方法每5000ms执行一次,采用固定延迟,即周期从每次先前调用的【完成时间】开始测量。

java 复制代码
@Scheduled(fixedDelay = 5000)  
public void doSomething() {
	// 定期运行的内容  
}

默认,固定延迟、固定速率和初始延迟的值将使用ms作时间单位。如想用不同时间单位,如s或min,可在 @Scheduled 配置 timeUnit 属性:

java 复制代码
@Scheduled(fixedDelay = 5, timeUnit = TimeUnit.SECONDS)
public void doSomething() {
}

2.2 fixedRate

如需固定速率执行,使用 fixedRate 属性。下面的方法每五秒(从每次【调用的开始时间】间隔测量)执行一次:

java 复制代码
@Scheduled(fixedRate = 5, timeUnit = TimeUnit.SECONDS)  
public void doSomething() {

}

固定延迟、固定速率的任务,可通过指示等待的时间量来指定初始延迟,然后再执行方法的第一次调用:

java 复制代码
@Scheduled(initialDelay=1000, fixedRate=5000)  
public void doSomething() {
	// 定期运行的内容
}

2.3 一次性任务

可只指定通过指示等待执行方法的时间量的初始延迟:

java 复制代码
@Scheduled(initialDelay=1000)
public void doSomething() {
	// 只运行一次
}

若简单的定期计划不够表达力,可用 cron 表达式:

java 复制代码
@Scheduled(cron="*/5 * * * * MON-FRI")  
public void doSomething() {
	// 仅在工作日运行的内容 
}

还可使用 zone 属性指定解析 cron 表达式的时区。

要计划的方法须有 void 返回值,且不接受任何参数。如果方法需要与应用程序上下文中的其他对象交互,那么这些对象通常已经通过依赖注入。

@Scheduled 是可重复注解。如在同一方法上找到几个 scheduled 声明,每个声明都将独立处理,为每个声明触发单独的触发器。因此,这样的共定位计划可并行重叠并立即连续执行多次。请确保你指定的 cron 表达式等不会意外重叠。

Spring Framework 4.3 开始,支持任何范围的 bean 上的 @Scheduled 方法。确保在运行时不初始化同一 @Scheduled 注解类的多个实例,除非你确实希望调度回调到每个这样的实例。

确保不要在使用 @Scheduled 注解并作为常规 Spring bean 注册到容器中的 bean 类上使用 @Configurable。否则,你将获得双重初始化(一次通过容器,一次通过 @Configurable 方面),其结果是每个 @Scheduled 方法被调用两次。

FAQ

问题

生产用@Scheduled注解写定时任务,5min执行一次:

java 复制代码
@Scheduled(cron = "0 0/5 * * * ?")
public void MyTimerJobSchedule() throws Exception {
  //省略具体业务逻辑
  System.out.println("五分钟执行一次");
}

过几天,领导通知说有问题,一查日志,发现是定时任务问题。本来应该是5min跑一次,结果日志发现,每天0点-3点正常,3-10点没执行;一直到10-11点之间才继续跑。

原因

发现可能是定时任务单线程模式导致任务阻塞。

继续分析日志,发现该定时任务的线程号是[Scheduling-1],除了执行自身的任务,还打印了其它定时任务的输出语句。

每天3点前,[Scheduling-1]线程在执行本人写的5min一次的定时任务,3点后,[Scheduling-1]线程会执行另一个比较耗时的定时任务,直到10点后,[Scheduling-1]线程才重新执行5min一次的定时任务。

看来,确实是由于@Scheduled定时任务默认使用单线程模式导致:一旦有一个定时任务比较耗时,就会影响到其它定时任务按时执行。

解决方法

在定时任务加@Async注解,并在启动类增加@EnableAsync注解,使用多线程模式执行定时任务。

备注: 参考网址:blog.csdn.net/LYM0721/art...

参考网址中有第二种解决方法,但是已说明不太好用,因此只用第一种解决方法就够了。

本文由博客一文多发平台 OpenWrite 发布!

相关推荐
带刺的坐椅15 分钟前
Solon v3.4.7, v3.5.6, v3.6.1 发布(国产优秀应用开发框架)
java·spring·solon
四谎真好看2 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程2 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t2 小时前
ZIP工具类
java·zip
lang201509282 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan3 小时前
第10章 Maven
java·maven
百锦再4 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说4 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多4 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
百锦再4 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven