Spring异步方法配置线程池

wen java案例 3

本文目录导读:

Spring异步方法配置线程池

  1. 基础配置方式
  2. 多线程池配置
  3. 完整的线程池配置示例
  4. 自定义拒绝策略
  5. 最佳实践建议

在Spring中配置异步方法的线程池,主要是通过@Async注解结合TaskExecutor实现,以下是几种常见的配置方式:

基础配置方式

使用配置文件(application.yml/application.properties)

spring:
  task:
    execution:
      pool:
        core-size: 5
        max-size: 10
        queue-capacity: 100
        keep-alive: 60s
      thread-name-prefix: async-task-

Java配置类

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("async-task-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) -> {
            System.err.println("异步方法执行异常: " + method.getName());
            System.err.println("异常信息: " + ex.getMessage());
        };
    }
}

多线程池配置

当需要不同的异步任务使用不同的线程池时:

@Configuration
@EnableAsync
public class MultipleAsyncConfig {
    @Bean("taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("task-");
        executor.initialize();
        return executor;
    }
    @Bean("notificationExecutor")
    public Executor notificationExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(3);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(50);
        executor.setThreadNamePrefix("notification-");
        executor.initialize();
        return executor;
    }
}

使用时就指定线程池:

@Service
public class AsyncService {
    @Async("taskExecutor")
    public CompletableFuture<String> processTask() {
        // 使用 taskExecutor 线程池
        return CompletableFuture.completedFuture("任务处理完成");
    }
    @Async("notificationExecutor")
    public void sendNotification() {
        // 使用 notificationExecutor 线程池
        System.out.println("发送通知");
    }
}

完整的线程池配置示例

@Configuration
@EnableAsync
public class ThreadPoolConfig {
    @Primary
    @Bean("asyncTaskExecutor")
    public Executor asyncTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数
        executor.setCorePoolSize(5);
        // 最大线程数
        executor.setMaxPoolSize(10);
        // 队列容量
        executor.setQueueCapacity(200);
        // 线程池维护线程所允许的空闲时间
        executor.setKeepAliveSeconds(60);
        // 线程前缀
        executor.setThreadNamePrefix("async-task-");
        // 拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 是否等待任务完成后再关闭
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 等待终止时间
        executor.setAwaitTerminationSeconds(60);
        executor.initialize();
        // 添加监控
        monitorThreadPool(executor);
        return executor;
    }
    private void monitorThreadPool(ThreadPoolTaskExecutor executor) {
        Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
            ThreadPoolExecutor threadPool = executor.getThreadPoolExecutor();
            System.out.println("=== 线程池状态监控 ===");
            System.out.println("核心线程数: " + executor.getCorePoolSize());
            System.out.println("最大线程数: " + executor.getMaxPoolSize());
            System.out.println("当前活动线程数: " + threadPool.getActiveCount());
            System.out.println("当前线程池大小: " + threadPool.getPoolSize());
            System.out.println("队列中等待任务数: " + threadPool.getQueue().size());
            System.out.println("已完成任务数: " + threadPool.getCompletedTaskCount());
            System.out.println("总任务数: " + threadPool.getTaskCount());
        }, 0, 30, TimeUnit.SECONDS);
    }
}

自定义拒绝策略

@Configuration
@EnableAsync
public class CustomRejectConfig {
    @Bean("customExecutor")
    public Executor customExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("custom-");
        // 自定义拒绝策略
        executor.setRejectedExecutionHandler((runnable, threadPoolExecutor) -> {
            System.err.println("任务被拒绝: " + runnable.toString());
            System.err.println("当前活动线程数: " + threadPoolExecutor.getActiveCount());
            System.err.println("队列大小: " + threadPoolExecutor.getQueue().size());
            // 可以选择重新尝试提交
            try {
                // 等待队列空闲
                if (!threadPoolExecutor.getQueue().offer(runnable, 5, TimeUnit.SECONDS)) {
                    System.err.println("队列仍然满,任务被丢弃");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        executor.initialize();
        return executor;
    }
}

最佳实践建议

配置建议:

  • 核心线程数:根据CPU核心数和任务类型设置,IO密集型可设置较大
  • 最大线程数:通常为核心线程数的2-3倍
  • 队列容量:根据任务量和内存大小调整
  • 拒绝策略:推荐使用CallerRunsPolicy保证任务不丢失

使用建议:

@Service
public class AsyncService {
    @Async
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void asyncTransactionalMethod() {
        // 注意:异步方法的事务是独立的
    }
    @Async
    public CompletableFuture<String> asyncWithReturn() {
        // 返回Future以便调用方获取结果或等待完成
        return CompletableFuture.completedFuture("结果");
    }
}

注意事项:

  1. 异步方法不能和调用者在同一个类中(避免代理失效)
  2. 异步方法默认使用代理,需要确保Spring的AOP生效
  3. 异步方法中的异常处理需要注意
  4. 事务管理在异步方法中是独立的

通过合理配置线程池,可以有效提升系统的异步处理能力和资源利用率。

抱歉,评论功能暂时关闭!