spring中异步任务注解@Async和@scheduled的使用
@Async
和 @Scheduled
都是 Spring 中处理异步任务的注解,但它们的设计目的、触发机制和使用场景有本质区别。以下是详细对比:
1. 核心目的不同
注解 | 核心目的 | 典型场景 |
---|---|---|
@Async | 异步执行方法 立即返回结果,后台处理耗时操作 | 发送邮件、调用外部 API、日志记录 |
@Scheduled | 定时任务调度 按计划周期/延迟执行任务 | 数据清理、定时统计、心跳检测 |
2. 触发机制对比
@Async 触发方式
被动触发:需要显式调用被注解的方法
调用即触发:每次方法调用都会提交新任务到线程池
@Scheduled 触发方式
主动触发:由 Spring 任务调度器自动触发
无需调用:根据配置的时间规则自动执行
3. 配置方式对比
@Async 配置
java
@Configuration @EnableAsync // 启用异步支持 public class AsyncConfig {@Beanpublic Executor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);return executor;} }
@Scheduled 配置
java
@Configuration @EnableScheduling // 启用定时任务支持 public class ScheduledConfig {@Beanpublic TaskScheduler taskScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();scheduler.setPoolSize(5);return scheduler;} }
4. 执行机制差异
特性 | @Async | @Scheduled |
---|---|---|
线程模型 | 使用线程池执行任务 | 使用任务调度器执行 |
默认线程行为 | SimpleAsyncTaskExecutor (每次新线程) | 单线程执行(需配置线程池防阻塞) |
任务依赖 | 可通过 CompletableFuture 链式调用 | 独立执行,无任务间依赖 |
异常处理 | 需实现 AsyncUncaughtExceptionHandler | 直接在方法内 try-catch |
任务取消 | 可通过 Future.cancel() 取消 | 通过 ScheduledFuture.cancel() 取消 |
5. 使用示例对比
@Async 示例
java
@Service public class EmailService {@Async // 异步执行public CompletableFuture<String> sendEmail(String content) {// 模拟耗时操作return CompletableFuture.completedFuture("发送成功: " + content);} }// 调用方 CompletableFuture<String> future = emailService.sendEmail("Hello"); future.thenAccept(result -> System.out.println(result)); // 异步回调
@Scheduled 示例
java
@Service public class CleanupService {@Scheduled(fixedRate = 30 * 60 * 1000) // 每30分钟执行一次public void clearTempFiles() {// 清理临时文件}@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行public void backupDatabase() {// 数据库备份} }