Spring Boot中@Async与@Scheduled协同及方法注解必要性咨询
Spring Boot中@Async与@Scheduled的协同工作及异步范围问题
先聊聊@Async和@Scheduled的协同逻辑:
- 要让这两个注解生效,必须在配置类上加上
@EnableScheduling(开启定时任务)和@EnableAsync(开启异步支持),就像示例里的Scheduler类那样。 - 被
@Scheduled标记的方法,默认会在Spring的调度线程池中同步执行——如果任务执行耗时久,会占着调度线程不放,要么导致后续的定时触发延迟,要么影响其他定时任务的执行。 - 给
@Scheduled的方法再加个@Async之后,情况就变了:调度器只是负责触发任务,触发后立刻释放线程,而任务的整个执行逻辑会被丢到异步线程池里跑。这样就彻底避免了长耗时任务阻塞调度线程的问题。
核心问题解答:是否需要给reportService.createEmptyDailyReports加@Async?
不需要,仅在createDailyReports()上添加@Async就足够让整个方法异步执行。
原因很简单:
- 当
@Async标注在createDailyReports方法上时,Spring会为这个方法生成代理对象。调度器触发任务时,会把整个方法的执行流程(包括里面调用reportService.createEmptyDailyReports的步骤)都放到异步线程中执行。 - 此时,
reportService的方法调用是在异步线程里同步完成的,但整个createDailyReports的执行已经脱离了调度线程池,完全达到了“整个定时任务异步执行”的需求。 - 只有两种情况需要给
reportService.createEmptyDailyReports单独加@Async:一是你希望这个方法在其他地方被调用时也能异步执行;二是你需要让这个方法的执行和createDailyReports里的其他逻辑并行处理。否则完全没必要多此一举。
示例代码:
@Configuration @EnableScheduling @ConditionalOnProperty(name = "scheduler.enabled", matchIfMissing = true) @RequiredArgsConstructor @EnableAsync public class Scheduler { private final ReportService reportService; @Scheduled(cron = "${scheduler.create-reports.cron}") @Async public void createDailyReports() { // TODO: Make request to team-service to find all students id's. Then create new empty reports List<Long> studentIdList = new ArrayList<>(); reportService.createEmptyDailyReports(studentIdList); } }
内容的提问来源于stack exchange,提问作者IvanDx
相关产品推荐
相关产品推荐

