Spring 多线程处理的几种方式

部署运行你感兴趣的模型镜像

Spring 多线程处理的几种方式

  1. @Async 注解 - 最简单的异步方式
  2. ThreadPoolTaskExecutor - 细粒度线程池控制
  3. CompletableFuture - 复杂任务编排
  4. 并行流 - 函数式并行处理
  5. WebFlux - 响应式编程
  6. 定时任务多线程 - 并发调度
  7. 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 提供了多种多线程处理方式,选择合适的方案需要考虑:

  1. 任务复杂度:简单任务用 @Async,复杂编排用 CompletableFuture
  2. 性能要求:高并发用 WebFlux,批处理用 Spring Batch
  3. 可维护性:优先使用 Spring 原生方案
  4. 监控需求:需要细粒度监控选择 ThreadPoolTaskExecutor

记住:没有最好的方案,只有最适合的方案

您可能感兴趣的与本文相关的镜像

FLUX.1-dev

FLUX.1-dev

图片生成
FLUX

FLUX.1-dev 是一个由 Black Forest Labs 创立的开源 AI 图像生成模型版本,它以其高质量和类似照片的真实感而闻名,并且比其他模型更有效率

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值