09.4 — 异步任务与定时任务
←**返回 进阶源码索引**
1. 定时任务
java
@Configuration
@EnableScheduling
public class SchedulingConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5);
scheduler.setThreadNamePrefix("scheduled-");
scheduler.setWaitForTasksToCompleteOnShutdown(true);
scheduler.setAwaitTerminationSeconds(30);
return scheduler;
}
}
@Component
public class ScheduledTasks {
// cron 表达式:秒 分 时 日 月 周
@Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点
public void dailyReport() {
System.out.println("生成日报...");
}
// 固定间隔(两次调用之间)
@Scheduled(fixedDelay = 5000) // 上次执行完 5 秒后
public void processDelay() {
System.out.println("Fixed delay task...");
}
// 固定速率(不考虑执行时间)
@Scheduled(fixedRate = 10000) // 每 10 秒执行一次
public void processRate() {
System.out.println("Fixed rate task...");
}
// 首次延迟
@Scheduled(initialDelay = 10000, fixedRate = 5000)
public void delayedTask() {
System.out.println("Delay 10s then every 5s");
}
}注意事项
- 默认单线程:默认的
@EnableScheduling使用单线程执行器,所有任务共享一个线程 - 配置线程池:必须配置
TaskScheduler避免任务互相阻塞 - 异常处理:schedule 不捕获异常,一个任务的异常不会影响其他任务(单线程模式下,未捕获异常会杀死线程池中的线程)
- 分布式锁:多实例部署时需配合分布式锁,防止任务重复执行
2. 异步支持
java
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex, method, params) -> {
log.error("Async method [{}] threw exception", method.getName(), ex);
};
}
}
@Component
public class AsyncService {
@Async
public CompletableFuture<String> processAsync(String data) {
// 异步执行
return CompletableFuture.completedFuture("Processed: " + data);
}
@Async
public void fireAndForget() {
// 无返回值异步
}
}@Async 失效场景
与 **@Transactional 同方法失效** 同理,
@Async也基于 AOP 代理。
java
@Service
public class NotificationService {
public void sendBatch() {
this.sendEmail(); // ❌ @Async 不生效(直接调用 this 引用)
}
@Async
public void sendEmail() {
// ...
}
}注意事项
- 默认代理方式:Spring Boot 默认使用 CGLIB 代理
- 返回值限制:只能返回
void或Future(AsyncResult、CompletableFuture) - 异常处理:无返回值方法抛出的异常由
AsyncUncaughtExceptionHandler处理 @Async+@Transactional:组合使用时注意——@Async让方法在独立线程执行,@Transactional在该线程的事务上下文中生效,两者互不干扰