java Spring Task
Spring Framework 提供了强大的任务调度和执行功能,主要包括定时任务(@Scheduled)、异步任务(@Async)和任务执行器(TaskExecutor)。下面我将详细介绍这些功能。
Spring Task 详细介绍
Spring Framework 提供了强大的任务调度和执行功能,主要包括定时任务(@Scheduled)、异步任务(@Async)和任务执行器(TaskExecutor)。下面我将详细介绍这些功能。
一、定时任务(Scheduled Tasks)
1. 基础配置
首先需要在配置类上添加@EnableScheduling注解启用定时任务功能:
@Configuration
@EnableScheduling
public class SchedulingConfig {
}
2. @Scheduled 注解详解
@Scheduled注解支持多种参数配置:
@Service
public class ScheduledService {
// 固定频率执行,单位毫秒
@Scheduled(fixedRate = 5000)
public void fixedRateTask() {
System.out.println("固定频率任务,每5秒执行一次");
}
// 固定延迟执行,上一次执行完成后延迟指定时间再执行
@Scheduled(fixedDelay = 3000)
public void fixedDelayTask() {
System.out.println("固定延迟任务,执行完成后3秒再执行");
}
// 初始延迟,第一次执行前延迟时间
@Scheduled(initialDelay = 1000, fixedRate = 5000)
public void initialDelayTask() {
System.out.println("初始延迟1秒,之后每5秒执行一次");
}
// Cron表达式
@Scheduled(cron = "0 0/5 * * * ?")
public void cronTask() {
System.out.println("每5分钟执行一次");
}
// 使用占位符从配置文件中读取
@Scheduled(cron = "${task.cron}")
public void configurableTask() {
System.out.println("可配置的定时任务");
}
}
3 Cron表达式语法详解及常用示例
Cron表达式是用于配置定时任务执行时间的强大工具,Spring Task完全支持标准Cron表达式语法。下面详细介绍语法规则和常用示例。
3.1 Cron表达式语法结构
标准Cron表达式由6或7个字段组成(年字段可选),字段之间用空格分隔:
秒 分 时 日 月 周 年(可选)
各字段含义及取值范围:
| 字段 | 允许值 | 允许的特殊字符 |
|---|---|---|
| 秒 | 0-59 | , - * / |
| 分 | 0-59 | , - * / |
| 时 | 0-23 | , - * / |
| 日 | 1-31 | , - * ? / L W C |
| 月 | 1-12或JAN-DEC | , - * / |
| 周 | 0-6或SUN-SAT | , - * ? / L C # |
| 年 | 1970-2099(可选) | , - * / |
3.2 特殊字符含义
*- 表示所有值(每…)?- 不指定值(用于日和周字段互斥)-- 指定范围(如1-5),- 指定多个值(如1,3,5)/- 指定增量(如0/15表示从0开始每15单位)L- 最后(Last)W- 最近工作日(Weekday)#- 第几个周几(如6#3表示第3个周五)
3.3 常用Cron表达式示例
3.3.1. 基础定时
| 表达式 | 说明 |
|---|---|
0 0/5 * * * ? |
每5分钟执行一次 |
0 0 * * * ? |
每小时执行一次 |
0 0 12 * * ? |
每天中午12点执行 |
0 15 10 ? * * |
每天10:15执行 |
0 15 10 * * ? |
同上,每天10:15执行 |
0 15 10 * * ? * |
同上,每天10:15执行 |
3.3.2. 工作日/周末
| 表达式 | 说明 |
|---|---|
0 0 9 ? * MON-FRI |
工作日每天9点执行 |
0 0 12 ? * SAT,SUN |
周末每天中午12点执行 |
3.3.3. 每月/每周特定时间
| 表达式 | 说明 |
|---|---|
0 0 10 15 * ? |
每月15号10点执行 |
0 0 12 1 * ? |
每月1号中午12点执行 |
0 0 10 ? * 6L |
每月最后一个周五10点执行 |
0 0 10 ? * 6#3 |
每月第3个周五10点执行 |
3.3.4. 复杂时间组合
| 表达式 | 说明 |
|---|---|
0 0 8-18 ? * MON-FRI |
工作日8点到18点每小时执行 |
0 0/30 9-17 ? * MON-FRI |
工作日9点到17点每半小时执行 |
0 0 12 ? * WED |
每周三中午12点执行 |
0 0 12 1/5 * ? |
每月从1号开始每5天中午12点执行 |
3.3.5. 特殊时间点
| 表达式 | 说明 |
|---|---|
0 0 0 1 1 ? |
每年1月1日0点执行(元旦) |
0 0 0 24 12 ? |
每年12月24日0点执行(平安夜) |
0 0 0 * * ? |
每天0点执行 |
0 0 0 1 * ? |
每月1日0点执行 |
3.4、Spring中的特殊用法
-
占位符支持:
@Scheduled(cron = "${jobs.cron.expression}") public void job() { // 任务逻辑 } -
宏表达式(Spring特有):
@yearly或@annually- 每年一次 (0 0 0 1 1 *)@monthly- 每月一次 (0 0 0 1 * *)@weekly- 每周一次 (0 0 0 ? * SUN)@daily或@midnight- 每天一次 (0 0 0 * * ?)@hourly- 每小时一次 (0 0 * * * ?)
使用示例:
@Scheduled(cron = "@hourly") public void hourlyJob() { // 每小时执行的任务 }
3.5、注意事项
-
日和周字段互斥:这两个字段中必须有一个是
?,否则会产生冲突- 正确:
0 0 0 ? * MON(每周一) - 正确:
0 0 0 1 * ?(每月1号) - 错误:
0 0 0 1 * MON(冲突)
- 正确:
-
Spring与标准Cron的区别:
- Spring中周字段:1=SUN, 2=MON,…,7=SAT
- 标准Unix Cron中:0=SUN, 1=MON,…,6=SAT
-
闰秒:Cron表达式不支持闰秒(60)
-
夏令时:在夏令时转换时可能会出现意外行为
3.6、在线工具推荐
通过合理使用Cron表达式,您可以精确控制Spring Task的执行时间,满足各种复杂的调度需求。
4. 动态定时任务
实现SchedulingConfigurer接口可以实现动态定时任务:
@Configuration
public class DynamicSchedulingConfig implements SchedulingConfigurer {
@Value("${dynamic.task.interval}")
private long interval;
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(
() -> System.out.println("动态定时任务执行"),
triggerContext -> {
// 可以动态计算下次执行时间
return new Date(System.currentTimeMillis() + interval);
}
);
}
}
二、异步任务(Async Tasks)
1. 基础配置
启用异步任务支持:
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean(name = "taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
}
2. @Async 注解使用
@Service
public class AsyncService {
@Async
public void asyncTaskWithoutReturn() {
System.out.println("执行无返回值的异步任务");
}
@Async
public Future<String> asyncTaskWithReturn() {
return new AsyncResult<>("异步任务结果");
}
@Async("taskExecutor") // 指定执行器
public void asyncTaskWithExecutor() {
System.out.println("使用特定线程池执行的异步任务");
}
}
3. 异常处理
@Configuration
public class AsyncExceptionConfig implements AsyncConfigurer {
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex, method, params) -> {
System.err.println("异步任务异常: " + method.getName());
ex.printStackTrace();
};
}
}
三、任务执行器(TaskExecutor)
Spring提供了多种TaskExecutor实现:
1. ThreadPoolTaskExecutor
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("MyExecutor-");
executor.initialize();
return executor;
}
2. 其他执行器
// 简单异步执行器
@Bean
public SimpleAsyncTaskExecutor simpleAsyncTaskExecutor() {
return new SimpleAsyncTaskExecutor();
}
// 同步执行器
@Bean
public SyncTaskExecutor syncTaskExecutor() {
return new SyncTaskExecutor();
}
// 定时任务执行器
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5);
scheduler.setThreadNamePrefix("Scheduler-");
return scheduler;
}
四、高级特性
1. 条件化任务执行
@Scheduled(fixedRate = 5000)
@ConditionalOnProperty(name = "task.enabled", havingValue = "true")
public void conditionalTask() {
System.out.println("条件满足时执行的任务");
}
2. 任务生命周期管理
@Service
public class TaskLifecycleService implements SchedulingConfigurer {
private ScheduledFuture<?> future;
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(1);
scheduler.initialize();
future = scheduler.scheduleAtFixedRate(
() -> System.out.println("可管理的任务"),
5000
);
}
public void pauseTask() {
if (future != null) {
future.cancel(false);
}
}
public void resumeTask() {
// 重新启动任务
}
}
3. 分布式任务调度
结合ShedLock实现分布式锁:
@Scheduled(cron = "0 0/5 * * * ?")
@SchedulerLock(name = "distributedTask", lockAtLeastFor = "4m", lockAtMostFor = "5m")
public void distributedTask() {
System.out.println("分布式环境下确保单实例执行的任务");
}
五、最佳实践
- 线程池配置:根据任务特性合理配置线程池大小
- 异常处理:确保异步任务有完善的异常处理机制
- 任务幂等性:确保任务可以安全地重复执行
- 资源清理:长时间运行的任务要妥善管理资源
- 监控:添加任务执行日志和监控指标
六、常见问题
-
任务不执行:
- 检查是否添加了
@EnableScheduling或@EnableAsync - 检查组件是否被Spring管理(
@Component等)
- 检查是否添加了
-
任务执行时间不准确:
- 检查任务执行时间是否超过间隔时间
- 考虑使用
fixedDelay代替fixedRate
-
线程池耗尽:
- 增加线程池大小
- 优化任务执行时间
Spring的任务调度功能非常强大且灵活,可以根据实际需求选择合适的实现方式。对于复杂场景,可以考虑集成Quartz等专业调度框架。
七 案例
订单状态定时处理
@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨一点触发
public void processCompletedOrder() {
log.info("处理已完成订单:{}", LocalDateTime.now());
List<Orders> ordersList = orderMapper.completedTimeoutOrder();
if (ordersList != null && !ordersList.isEmpty()) {
for (Orders order : ordersList) {
order.setStatus(Orders.COMPLETED);
}
}
if (!ordersList.isEmpty()) {
orderMapper.updateBatch(ordersList);
}
}
更多推荐



所有评论(0)