Spring Boot接口异步改造及多请求串行执行方案咨询
异步改造及串行执行方案
一、@Async注解的必要配置
仅添加@Async注解无法实现异步效果,必须补充如下配置:
- 首先在Spring Boot主启动类上添加
@EnableAsync注解,开启Spring的异步方法支持,否则@Async注解会被直接忽略。 - 注意@Async注解需要标注在
public方法上,且不能由同一个类内部的方法直接调用,否则Spring AOP代理不生效,异步逻辑不会执行。
建议你将@Async注解标注在
CppService的loadData()方法上,不要标注在Controller方法上,避免同类调用失效问题。
二、串行排队执行实现方案
你需要的"同一时间仅执行一个任务,后续请求排队等待前序任务完成"的需求,只需要自定义一个单线程的异步线程池即可实现,所有提交的异步任务会按提交顺序串行执行:
第一步:添加单线程异步池配置
创建异步配置类:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.ThreadPoolExecutor; @Configuration public class AsyncConfig { @Bean(name = "singleThreadAsyncPool") public ThreadPoolTaskExecutor singleThreadAsyncPool() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 核心线程数和最大线程数都设为1,保证同一时间仅执行一个任务 executor.setCorePoolSize(1); executor.setMaxPoolSize(1); // 等待队列容量,可根据业务预期的最大排队请求数调整 executor.setQueueCapacity(50); executor.setThreadNamePrefix("delta-load-"); // 队列满时的拒绝策略,这里用CallerRunsPolicy会由调用线程执行任务,也可以改为AbortPolicy直接抛异常 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } }
第二步:给异步方法指定线程池
修改CppService的loadData方法,添加@Async注解并指定使用自定义的单线程池:
@Async("singleThreadAsyncPool") public void loadData() { // 原有业务逻辑不变 }
第三步:Controller层保持原有逻辑即可
@Operation(summary = "load operation") @PostMapping(value = "delta/load") public void sendDeltaOutbound() { cppService.loadData(); }
三、可选优化
如果需要给调用方返回任务状态(比如告知当前有任务正在执行,已经进入排队),可以新增一个全局的原子计数器统计排队中+执行中的任务总数,接口调用时直接返回该数值即可。
内容的提问来源于stack exchange,提问作者Aruna
相关产品推荐
相关产品推荐

