Spring 多线程处理的几种方式
- @Async 注解 - 最简单的异步方式
- ThreadPoolTaskExecutor - 细粒度线程池控制
- CompletableFuture - 复杂任务编排
- 并行流 - 函数式并行处理
- WebFlux - 响应式编程
- 定时任务多线程 - 并发调度
- Spring Batch - 批处理并行
1. @Async 注解方式
1.1 基本使用
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-");
executor.initialize();
return executor;
}
}
@Service
public class AsyncService {
@Async
public void asyncMethod() {
// 异步执行的代码
System.out.println("执行线程:" + Thread.currentThread().getName());
}
@Async
public CompletableFuture<String> asyncMethodWithReturn() {
// 返回结果的异步方法
return CompletableFuture.completedFuture("异步结果");
}
}
1.2 优缺点
优点:
- 使用简单,声明式编程
- 与 Spring 集成良好
- 支持返回 Future/CompletableFuture
缺点:
- 必须在不同类中调用才生效(代理机制限制)
- 异常处理需要额外配置
- 不支持私有方法
2. ThreadPoolTaskExecutor
2.1 基本配置
@Configuration
public class ThreadPoolConfig {
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10); // 核心线程数
executor.setMaxPoolSize(20); // 最大线程数
executor.setQueueCapacity(200); // 队列容量
executor.setKeepAliveSeconds(60); // 线程存活时间
executor.setThreadNamePrefix("custom-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
}
}
@Service
public class TaskService {
@Autowired
private ThreadPoolTaskExecutor executor;
public void executeTask() {
executor.execute(() -> {
// 执行任务
System.out.println("任务执行中...");
});
}
public Future<String> submitTask() {
return executor.submit(() -> {
// 有返回值的任务
return "任务结果";
});
}
}
2.2 拒绝策略
- CallerRunsPolicy:调用者线程执行任务
- AbortPolicy:抛出异常(默认)
- DiscardPolicy:直接丢弃
- DiscardOldestPolicy:丢弃最老的任务
3. CompletableFuture
3.1 基本使用
@Service
public class CompletableFutureService {
public void basicUsage() {
// 无返回值异步任务
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
System.out.println("异步任务执行");
});
// 有返回值异步任务
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
return "异步结果";
});
// 自定义线程池
Executor executor = Executors.newFixedThreadPool(10);
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
return "使用自定义线程池";
}, executor);
}
public void chainedOperations() {
CompletableFuture<String> future = CompletableFuture
.supplyAsync(() -> "Hello")
.thenApply(s -> s + " World")
.thenApply(String::toUpperCase);
// 组合多个 CompletableFuture
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Result1");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Result2");
CompletableFuture<String> combined = future1.thenCombine(future2,
(result1, result2) -> result1 + " + " + result2);
}
public void exceptionHandling() {
CompletableFuture<String> future = CompletableFuture
.supplyAsync(() -> {
if (true) throw new RuntimeException("错误");
return "成功";
})
.exceptionally(ex -> {
System.out.println("异常:" + ex.getMessage());
return "默认值";
})
.thenApply(result -> "最终结果:" + result);
}
}
4. 并行流 (Parallel Streams)
4.1 基本使用
@Service
public class ParallelStreamService {
public void processInParallel() {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 并行处理
List<Integer> result = numbers.parallelStream()
.map(n -> {
// 模拟耗时操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return n * 2;
})
.collect(Collectors.toList());
// 自定义线程池
ForkJoinPool customThreadPool = new ForkJoinPool(4);
try {
List<Integer> customResult = customThreadPool.submit(() ->
numbers.parallelStream()
.map(n -> n * 2)
.collect(Collectors.toList())
).get();
} catch (Exception e) {
e.printStackTrace();
} finally {
customThreadPool.shutdown();
}
}
}
4.2 注意事项
- 适合 CPU 密集型任务
- 数据量较小时可能性能反而下降
- 使用公共 ForkJoinPool,可能影响其他并行流
5. Spring WebFlux (响应式编程)
5.1 基本使用
@RestController
@RequestMapping("/reactive")
public class ReactiveController {
@GetMapping("/mono")
public Mono<String> getMono() {
return Mono.just("Hello")
.delayElement(Duration.ofSeconds(1))
.map(String::toUpperCase);
}
@GetMapping("/flux")
public Flux<Integer> getFlux() {
return Flux.range(1, 10)
.delayElements(Duration.ofMillis(100))
.map(i -> i * 2);
}
@GetMapping("/parallel")
public Flux<Integer> parallel() {
return Flux.range(1, 10)
.parallel(4) // 使用4个线程并行处理
.runOn(Schedulers.parallel())
.map(i -> {
// 耗时操作
return i * 2;
})
.sequential(); // 转回顺序流
}
}
6. 定时任务多线程
6.1 @Scheduled 配置
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
scheduler.setThreadNamePrefix("scheduled-");
scheduler.initialize();
taskRegistrar.setScheduler(scheduler);
}
}
@Component
public class ScheduledTasks {
@Scheduled(fixedDelay = 5000)
public void task1() {
System.out.println("定时任务1:" + Thread.currentThread().getName());
}
@Scheduled(cron = "0 */5 * * * ?")
public void task2() {
System.out.println("定时任务2:" + Thread.currentThread().getName());
}
}
7. 批处理多线程 (Spring Batch)
7.1 并行步骤
@Configuration
public class BatchConfig {
@Bean
public Job parallelJob(JobBuilderFactory jobBuilderFactory,
StepBuilderFactory stepBuilderFactory) {
return jobBuilderFactory.get("parallelJob")
.start(parallelFlow(stepBuilderFactory))
.end()
.build();
}
@Bean
public Flow parallelFlow(StepBuilderFactory stepBuilderFactory) {
return new FlowBuilder<Flow>("parallelFlow")
.split(new SimpleAsyncTaskExecutor())
.add(flow1(stepBuilderFactory), flow2(stepBuilderFactory))
.build();
}
@Bean
public Step partitionStep(StepBuilderFactory stepBuilderFactory) {
return stepBuilderFactory.get("partitionStep")
.partitioner("slaveStep", partitioner())
.step(slaveStep())
.gridSize(4) // 4个线程并行处理
.taskExecutor(taskExecutor())
.build();
}
}
8. 最佳实践
8.1 线程池配置建议
@Configuration
public class OptimalThreadPoolConfig {
@Bean
public ThreadPoolTaskExecutor optimalExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// CPU密集型:线程数 = CPU核心数 + 1
int cpuCores = Runtime.getRuntime().availableProcessors();
executor.setCorePoolSize(cpuCores + 1);
// IO密集型:线程数 = CPU核心数 * 2
// executor.setCorePoolSize(cpuCores * 2);
executor.setMaxPoolSize(cpuCores * 2);
executor.setQueueCapacity(1000);
executor.setThreadNamePrefix("optimal-");
// 线程池监控
executor.setTaskDecorator(runnable -> {
return () -> {
long start = System.currentTimeMillis();
try {
runnable.run();
} finally {
long duration = System.currentTimeMillis() - start;
System.out.println("Task duration: " + duration + "ms");
}
};
});
executor.initialize();
return executor;
}
}
8.2 异常处理
@Component
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
System.err.println("异步方法异常:" + method.getName());
System.err.println("异常信息:" + ex.getMessage());
// 记录日志、发送告警等
}
}
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}
8.3 监控和管理
@RestController
@RequestMapping("/thread-pool")
public class ThreadPoolMonitor {
@Autowired
private ThreadPoolTaskExecutor executor;
@GetMapping("/status")
public Map<String, Object> getStatus() {
Map<String, Object> status = new HashMap<>();
status.put("poolSize", executor.getPoolSize());
status.put("activeCount", executor.getActiveCount());
status.put("queueSize", executor.getThreadPoolExecutor().getQueue().size());
status.put("completedTaskCount", executor.getThreadPoolExecutor().getCompletedTaskCount());
return status;
}
@PostMapping("/resize")
public void resize(@RequestParam int coreSize, @RequestParam int maxSize) {
executor.setCorePoolSize(coreSize);
executor.setMaxPoolSize(maxSize);
}
}
9. 选择建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 简单异步任务 | @Async | 使用简单,Spring原生支持 |
| 复杂任务编排 | CompletableFuture | 强大的组合和链式调用能力 |
| 批量数据处理 | 并行流 | 简洁的函数式编程 |
| Web响应式编程 | WebFlux | 非阻塞IO,高并发 |
| 定时任务 | @Scheduled + 线程池 | Spring原生支持 |
| 大规模批处理 | Spring Batch | 专业的批处理框架 |
| 细粒度控制 | ThreadPoolTaskExecutor | 完全控制线程池参数 |
10. 常见问题
10.1 @Async 失效问题
- 同类方法调用不生效(使用 self-injection 或分离到不同类)
- 没有添加 @EnableAsync 注解
- 方法必须是 public
10.2 线程池阻塞
- 队列容量设置过小
- 拒绝策略不当
- 任务执行时间过长
10.3 内存泄漏
- ThreadLocal 未清理
- 线程池未正确关闭
- 大对象在线程中持有
总结
Spring 提供了多种多线程处理方式,选择合适的方案需要考虑:
- 任务复杂度:简单任务用 @Async,复杂编排用 CompletableFuture
- 性能要求:高并发用 WebFlux,批处理用 Spring Batch
- 可维护性:优先使用 Spring 原生方案
- 监控需求:需要细粒度监控选择 ThreadPoolTaskExecutor
记住:没有最好的方案,只有最适合的方案。
1468

被折叠的 条评论
为什么被折叠?



