本文目录导读:

在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("结果");
}
}
注意事项:
- 异步方法不能和调用者在同一个类中(避免代理失效)
- 异步方法默认使用代理,需要确保Spring的AOP生效
- 异步方法中的异常处理需要注意
- 事务管理在异步方法中是独立的
通过合理配置线程池,可以有效提升系统的异步处理能力和资源利用率。