Spring Web方法并发线程数限制方案咨询
解决方案
当然可以实现限制固定线程数处理请求、过载请求排队的需求,核心思路是用固定大小线程池替代单线程同步锁,既保证并发度控制在服务器可承受的10个线程,又能让超出的请求进入队列等待。
方案1:自定义线程池(Java原生实现)
直接使用ThreadPoolExecutor创建固定大小的线程池,核心线程数和最大线程数设为10,任务队列可选择无界或有界类型(根据业务需求调整队列容量)。
- 调整
CalculateBean,移除synchronized修饰符(线程池已控制并发数,无需额外锁):
public class CalculateBean { public long calculateTask(params...) { // 修正命名为小驼峰,符合Java规范 long result = 0; // 原代码中long为基本类型,不能赋值null,改为合理默认值 ... // 原有计算逻辑 return result; } }
- 在SOAP接口类中初始化单例线程池,提交任务并同步等待结果:
// 线程池定义为单例,避免重复创建浪费资源 private final ExecutorService calculateExecutor = new ThreadPoolExecutor( 10, // 核心线程数 10, // 最大线程数 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>() // 无界队列,超出10并发的请求自动进入队列等待 // 若需限制队列长度,可改为new LinkedBlockingQueue<>(1000),超出后触发拒绝策略 ); @WebMethod(operationName="calculateWebMethod", action="calculateWebMethod") public CalculateWebMethodResponse calculateWebMethod( @WebParam(name="param1") String param1, @WebParam(name="param2") String param2, ... ) { ... // 提交计算任务到线程池 Future<Long> future = calculateExecutor.submit(() -> { CalculateBean bean = new CalculateBean(); return bean.calculateTask(...params); }); try { long webMethodResult = future.get(); // 等待任务执行完成 return new CalculateWebMethodResponse(webMethodResult); } catch (InterruptedException | ExecutionException e) { // 处理任务执行异常,返回错误响应 throw new WebServiceException("计算任务执行失败", e); } }
方案2:Spring @Async + 自定义线程池(贴合Spring生态)
如果是Spring管理的应用,用@Async注解配合自定义线程池配置,代码更简洁:
- 配置线程池(注册为Spring Bean):
@Configuration @EnableAsync public class AsyncConfig { @Bean(name = "calculateThreadPool") public Executor calculateThreadPool() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(10); executor.setQueueCapacity(Integer.MAX_VALUE); // 无界队列 executor.setThreadNamePrefix("Calculate-Thread-"); executor.initialize(); return executor; } }
- 改造
CalculateBean为Spring Bean,添加@Async注解指定线程池:
@Component public class CalculateBean { @Async("calculateThreadPool") public CompletableFuture<Long> calculateTask(params...) { long result = 0; ... // 原有计算逻辑 return CompletableFuture.completedFuture(result); } }
- 在SOAP接口中注入
CalculateBean并调用:
@Autowired private CalculateBean calculateBean; @WebMethod(operationName="calculateWebMethod", action="calculateWebMethod") public CalculateWebMethodResponse calculateWebMethod( @WebParam(name="param1") String param1, @WebParam(name="param2") String param2, ... ) { ... try { CompletableFuture<Long> future = calculateBean.calculateTask(...params); long webMethodResult = future.get(); return new CalculateWebMethodResponse(webMethodResult); } catch (InterruptedException | ExecutionException e) { throw new WebServiceException("计算任务执行失败", e); } }
注意事项
- 若需限制队列长度,可将队列改为有界类型(如
new LinkedBlockingQueue<>(500)),同时指定拒绝策略(比如ThreadPoolExecutor.CallerRunsPolicy让调用线程执行,或自定义策略直接返回错误响应)。 - 线程池必须保证单例,避免重复创建导致资源耗尽。
- 完善异常处理逻辑,避免任务执行异常导致请求无响应。
内容的提问来源于stack exchange,提问作者Cesar Lopes
相关产品推荐
相关产品推荐

