前言
在我们的日常生活和工作中,时间管理是一项至关重要的技能。随着各种复杂任务的增加和时间压力的不断增加,如何更好地分配和利用时间成为了一项迫切需要解决的问题。在这样的背景下,定时任务成为了一种非常有效的解决方案。
定时任务,顾名思义,即按照预定的时间点或时间间隔定期执行指定的任务。它可以帮助我们自动化一些重复性的、繁琐的工作,从而节省时间和精力,提高效率。
本文将介绍定时任务的基本概念、应用场景以及如何使用定时任务来优化我们的生活和工作。
一、开始学习
本次案例以一个简单的下单操作进行讲解!
1、新建任务,结构如下
2、添加 spring 依赖
<!-- spring 的核心依赖 -->
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.5</version>
</dependency>
</dependencies>
3、在 service 包下新建一个 OrderService 类
@Service
@Slf4j
public class OrderService {
public void backup(){
log.info("备份订单");
}
}
这是一个简单的Java类,名为OrderService。该类使用了两个注解:@Service和@Slf4j。
@Service注解用于标识该类为Spring的服务组件,可以被自动注入到其他需要调用该服务的类中。
@Slf4j注解是Lombok提供的一个注解,在编译期间会自动生成一个名为log的日志对象,主要是为了输出方法中的 “备份订单”。
在该类中,有一个名为backup的方法。该方法用于备份订单,并在控制台输出一条日志记录。通过使用@Slf4j注解,我们可以方便地使用log对象输出日志信息。
4、在 config 包下新建一个配置类 AppConfig
@Configuration
@ComponentScan(basePackages = "edu.nf.ch24")
// 启用定时任务注解处理器
@EnableScheduling
public class AppConfig implements SchedulingConfigurer {
/**
* 装配一个自定义的定时任务线程
*
* @return
*/
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
// 创建定时任务线程池
ThreadPoolTaskScheduler poolTaskScheduler = new ThreadPoolTaskScheduler();
// 设置池的线程大小
poolTaskScheduler.setPoolSize(10);
// 设置线程名称的前缀
poolTaskScheduler.setThreadNamePrefix("任务线程—");
return poolTaskScheduler;
}
/**
* 注册自定义的线程池
*
* @param taskRegistrar
*/
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
// 注册定时任务线程池
taskRegistrar.setTaskScheduler(taskScheduler());
}
}
其中使用了
@ComponentScan
注解来指定扫描的基础包路径为edu.nf.ch24
,并通过@EnableScheduling
启用了定时任务的注解处理器。此外,在
AppConfig
中实现了SchedulingConfigurer
接口,并重写了configureTasks
方法。在该方法中,通过taskRegistrar.setTaskScheduler(taskScheduler())
注册了一个自定义的定时任务线程池,使用taskScheduler()
方法创建了一个ThreadPoolTaskScheduler
对象,并设置了线程池的大小为 10,线程名称的前缀为 "任务线程—"。最终,我们可以通过将
AppConfig
作为配置类传递给 Spring 容器来启动应用程序,并在edu.nf.ch24
包下的定时任务相关类中使用注解来定义定时任务,由定时任务注解处理器负责创建相应的定时任务并在指定的时间执行。这个类
AppConfig
的作用是用来配置 Spring 容器的,具体来说,它定义了一个名为taskScheduler
的 Bean,并将其注册到 Spring 容器中。这个 Bean 是一个定时任务线程池,用来执行我们在应用程序中定义的定时任务。通过
@Bean
注解和taskScheduler()
方法定义了一个ThreadPoolTaskScheduler
对象,并对其进行一些属性的配置,如设置线程池大小和线程名称前缀等。然后,在configureTasks
方法中将taskScheduler
注册到了taskRegistrar
中,以便在应用程序中使用。另外,通过
@ComponentScan(basePackages = "edu.nf.ch24")
注解指定了需要扫描的基础包路径为edu.nf.ch24
,这样 Spring 容器就能够找到该路径下定义的所有 Bean,并进行相应的管理和注入。最后,通过
@EnableScheduling
注解启用了 Spring 的定时任务注解处理器,使得我们可以在应用程序中使用注解来定义定时任务,而不需要手动编写定时任务的相关代码,从而提高了开发效率。
5、在 task 包下新建一个 OrderTask 类
/**
* @Date 2023-10-13
* @Author qiu
* 订单定时器,定时触发
*/
@Component
@RequiredArgsConstructor
public class OrderTask {
public final OrderService orderService;
/**
* 定时任务方法
* 使用 @Scheduled 注解标注当前方法为一个定时任务方法
* 并且使用 cron 表达式来设定执行的时间
*/
@Scheduled(cron = "0/5 * * * * ?")
public void executeBackup() {
orderService.backup();
}
}
这是一个订单定时器类
OrderTask
,用来执行一些定时任务。它使用了@Component
注解将其标记为 Spring 容器中的组件,在应用程序启动时会由 Spring 自动扫描并加载。该类通过构造函数注入了一个
OrderService
实例,用来执行一些具体操作。注意到它的构造函数使用了@RequiredArgsConstructor
注解,该注解是 Lombok 库提供的,可以帮助我们自动生成一个包含所有成员变量的构造函数,避免了手写构造函数的繁琐。在
OrderTask
类中,定义了一个名为executeBackup()
的方法,使用了@Scheduled(cron = "0/5 * * * * ?")
注解,表示该方法是一个定时任务,并且它将在 Cron 表达式 "0/5 * * * * ?" 指定的时刻执行。具体来说,该表达式表示每隔 5 秒钟执行一次。在
executeBackup()
方法中,调用了orderService.backup()
方法,该方法用于执行一些备份操作。总之,这个类用于定义一个周期性执行的定时任务,它依赖于
OrderService
并使用了 Spring 的定时任务注解@Scheduled
。当定时任务启动后,它将会间隔一定时间执行orderService.backup()
方法,用于进行一些数据备份操作。
来讲一下 Cron 表达式:
Cron 表达式是一种用于指定时间的字符串表达式,通常用来表示定时任务的执行时间。Cron 表达式由 6 或 7 个字段组成,每个字段之间用空格分隔,其格式如下:
<秒> <分> <时> <日> <月> <周> [年]
其中,秒
、分
、时
、日
、月
和 周
是必需的字段,它们分别表示秒、分、小时、日期、月份和星期。每个字段可以是一个具体值、一个范围、一个列表或者一个通配符。
以下是一些常用的 Cron 表达式示例:
"0 * * * * ?"
表示每个整分钟触发一次。"0/5 * * * * ?"
表示每隔 5 秒钟触发一次。"0 0/15 8-20 * * ?"
表示每天上午 8 点到晚上 8 点之间,每隔 15 分钟触发一次。"0 0 12 ? * WED"
表示每个星期三的中午 12 点触发一次。"0 0 10,14,16 * * ?"
表示每天上午 10 点、下午 2 点和下午 4 点各触发一次。"0 0/30 9-17 * * MON-FRI"
表示每个工作日上午 9 点到下午 5 点之间,每隔 30 分钟触发一次。
还有一些特殊符号也可以用来表示 Cron 表达式:
*
表示所有可能的值。-
表示一个范围。,
表示多个值,用逗号隔开。/
表示增量,如0/5
表示从 0 开始,每隔 5 秒一次。?
表示未指定的值,用于日和星期字段。如果日和星期都未指定,则表示每天都触发一次。#
表示某个月份的第几个星期几,如2#1
表示每个月的第一个周一。
Cron 表达式非常灵活,可以根据不同的场景自由组合。但是需要注意的是,应该避免使用过于复杂的表达式,以免造成混淆和误解。
6、测试
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
}
}
运行结果
只要执行了这个程序,初始化容器后就会启动AppConfig的注解,定时任务就是开启了。
二、使用定时任务有什么好处
使用定时任务有以下几个好处:
自动化执行:通过设置定时任务,可以让程序自动按计划执行,无需手动干预。这能够提高系统的可靠性和稳定性,避免人为错误或遗漏。
提高效率:定时任务可以在后台自动执行重复性的、耗时的操作,如数据备份、日志清理、报表生成等,从而释放人力资源,提高工作效率。
实时性和准确性:通过定时任务,可以及时地处理一些需要在特定时间点触发的事件,如发送定时通知、更新缓存、执行数据同步等,保证操作的实时性和准确性。
节省资源:定时任务可以在非高峰期执行一些资源密集型的操作,以避免对正常业务操作的影响。例如,在低访问量的时段执行数据库维护操作,或在夜间执行数据清理操作,以充分利用系统资源。
延迟执行:一些任务可能需要在未来的某个时间点触发,而不是立即执行。通过定时任务,可以预先设置好任务的执行时间,以满足特定的业务需求。
总的来说,使用定时任务可以提高系统的自动化程度,降低人工干预的需求,提高工作效率和系统可靠性,同时能够实现一些特定的业务需求,提供更好的用户体验。
三、gitee 案例
案例完整地址:https://gitee.com/qiu-feng1/spring-framework.git