在Java后端开发中,线程池是处理并发任务的基础设施。Spring Boot通过ThreadPoolTaskExecutor对Java原生线程池进行了深度封装,提供了更符合Spring生态的线程管理方案。我们先从最基础的线程池类型开始理解。
Java通过Executors类提供了四种基础线程池实现:
SingleThreadExecutor:
FixedThreadPool:
CachedThreadPool:
ScheduledThreadPool:
注意:阿里巴巴Java开发规范明确禁止使用Executors创建线程池,推荐通过ThreadPoolExecutor构造函数显式创建,以避免资源耗尽风险。
Spring的线程池实现相比原生方案有几个显著优势:
配置集中化:
properties复制# application.properties
spring.task.execution.pool.core-size=5
spring.task.execution.pool.max-size=10
spring.task.execution.pool.queue-capacity=100
生命周期管理:
java复制@PreDestroy
public void destroy() {
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
监控增强:
java复制// 获取线程池运行状态
int activeCount = executor.getActiveCount();
long completedTaskCount = executor.getThreadPoolExecutor().getCompletedTaskCount();
最常用的线程池配置方式:
java复制@Bean(name = "businessThreadPool")
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 常驻线程数
executor.setMaxPoolSize(20); // 最大线程数
executor.setQueueCapacity(100); // 队列容量
executor.setThreadNamePrefix("biz-thread-"); // 线程名前缀
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setAllowCoreThreadTimeOut(true); // 核心线程允许超时回收
executor.setKeepAliveSeconds(60); // 线程空闲时间
executor.initialize();
return executor;
}
结合Spring的@Value注解实现动态配置:
java复制@Value("${thread.pool.core.size:5}")
private int corePoolSize;
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
// 其他配置...
}
实现AsyncConfigurer接口进行全局配置:
java复制@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
// 其他配置...
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex, method, params) -> {
log.error("异步任务执行异常 - 方法: {}, 参数: {}", method.getName(), params, ex);
// 发送告警邮件等处理...
};
}
}
实现RejectedExecutionHandler接口:
java复制public class LogRejectedPolicy implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
log.warn("任务被拒绝, 当前活跃线程数: {}, 队列大小: {}",
executor.getActiveCount(), executor.getQueue().size());
// 可在此处实现降级逻辑
if (!executor.isShutdown()) {
r.run();
}
}
}
java复制@Async("businessThreadPool")
public CompletableFuture<String> asyncProcess(String input) {
// 模拟耗时操作
Thread.sleep(1000);
return CompletableFuture.completedFuture(input.toUpperCase());
}
java复制@Async
public CompletableFuture<Void> asyncWithException() {
try {
// 业务逻辑
} catch (Exception e) {
log.error("异步任务异常", e);
throw new AsyncException("业务处理失败", e);
}
}
java复制CompletableFuture.supplyAsync(() -> fetchUserData(userId), executor)
.thenApplyAsync(user -> enrichUserData(user), executor)
.thenAcceptAsync(result -> saveUserData(result), executor)
.exceptionally(ex -> {
log.error("用户数据处理链异常", ex);
return null;
});
java复制CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() -> userService.getUser(id));
CompletableFuture<Order> orderFuture = CompletableFuture.supplyAsync(() -> orderService.getLatestOrder(id));
userFuture.thenCombine(orderFuture, (user, order) -> {
UserOrderVO vo = new UserOrderVO();
vo.setUser(user);
vo.setOrder(order);
return vo;
}).thenAccept(System.out::println);
java复制@Scheduled(fixedRate = 5000) // 固定速率
public void reportCurrentTime() {
log.info("定时任务执行: {}", LocalDateTime.now());
}
@Scheduled(cron = "0 0 12 * * ?") // 每天中午12点
public void dailyJob() {
// 日终批处理
}
java复制@Autowired
private ThreadPoolTaskScheduler taskScheduler;
public void startDynamicTask(String cron) {
taskScheduler.schedule(() -> {
// 任务逻辑
}, new CronTrigger(cron));
}
java复制@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
scheduler.setThreadNamePrefix("scheduled-task-");
scheduler.setAwaitTerminationSeconds(60);
scheduler.setWaitForTasksToCompleteOnShutdown(true);
return scheduler;
}
java复制// 创建带监控的线程池
ListeningExecutorService executor = MoreExecutors.listeningDecorator(
new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100),
new ThreadFactoryBuilder().setNameFormat("guava-pool-%d").build()));
// 带回调的执行
ListenableFuture<String> future = executor.submit(() -> "result");
Futures.addCallback(future, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
// 成功处理
}
@Override
public void onFailure(Throwable t) {
// 异常处理
}
}, executor);
java复制// 快速创建线程池
ExecutorService executor = ThreadUtil.newExecutor(2, 5, 100);
// 异步执行
ThreadUtil.execAsync(() -> {
// 任务逻辑
}, true);
// 定时任务
CronUtil.schedule("*/5 * * * * *", (Task) () -> {
// 每5秒执行
});
java复制@Scheduled(fixedRate = 60000)
public void monitorThreadPool() {
ThreadPoolExecutor executor = taskExecutor.getThreadPoolExecutor();
metrics.gauge("thread.pool.active.count", executor.getActiveCount());
metrics.gauge("thread.pool.queue.size", executor.getQueue().size());
metrics.gauge("thread.pool.completed.tasks", executor.getCompletedTaskCount());
}
java复制@PreDestroy
public void gracefulShutdown() {
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
队列选择策略:
参数调优公式:
code复制最佳线程数 = CPU核心数 * (1 + 等待时间/计算时间)
例如:8核CPU,任务50%时间在等待,则线程数约为8*(1+1)=16
常见避坑指南:
性能优化技巧:
在实际项目中,我通常会为不同类型的任务创建独立的线程池,比如:
这种隔离策略可以避免某个任务类型异常导致整个系统线程资源耗尽。同时建议在项目启动时预加载核心线程,减少首次请求的延迟:
java复制@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 常规配置...
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.initialize();
// 预热核心线程
executor.prestartAllCoreThreads();
return executor;
}