整理一下在java多线程的使用过程中使用线程池的方式,代码示例见https://github.com/2Red1Blue/java-jvm-tuning其中的spring-threadpool模块
todo: 待补充一份动态线程池的实现: promethus+nacos/apollo,暂时没时间写了,等有空补充上来
单线程池(SingleThreadExecutor)
固定线程池(FixedThreadPool)
缓存线程池(CachedThreadPool)
定时任务线程池(ScheduledThreadPool)
Spring的ThreadPoolTaskExecutor是对Java ThreadPoolExecutor的封装,具有以下特点:
更好的Spring集成
增强的功能
配置更灵活
使用建议
生命周期管理
配置方式
功能扩展
配置方式
@EnableAsync // 在配置类上启用异步
@Configuration
public class AsyncConfig {
@Bean("threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
// 配置线程池
}
}
使用方式
@Async("threadPoolTaskExecutor")
public CompletableFuture asyncMethod() {
// 异步方法实现
}
注意事项
最佳实践
AsyncConfigurer接口是Spring提供的用于配置异步执行的接口,它提供了两个重要方法:
配置方式
@Configuration
public class AsyncExecutorConfig implements AsyncConfigurer {
@Value(“${thread-pool.core-pool-size}”)
private int corePoolSize;
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("async-");
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex, method, params) -> {
// 处理未捕获的异步异常
};
}
}
特点
基本使用
// 创建异步任务
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
return “结果”;
}, executor);
// 处理结果
future.thenAccept(result -> {
System.out.println(result);
});
常用方法
// 组合多个异步任务
CompletableFuture future1 = CompletableFuture.supplyAsync(() -> “Hello”);
CompletableFuture future2 = CompletableFuture.supplyAsync(() -> “World”);
CompletableFuture combined = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
// 异常处理
future.exceptionally(throwable -> “默认值”)
.thenAccept(System.out::println);
// 等待多个任务完成
CompletableFuture.allOf(future1, future2).join();
使用建议
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix("spring-thread-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
优点:
适用场景:
优点:
适用场景:
优点:
适用场景:
优点:
适用场景:
优点:
适用场景:
@Scheduled注解方式
@Scheduled(fixedRate = 5000) // 固定速率执行
public void fixedRateTask() {
// 任务代码
}
@Scheduled(cron = "0 0 12 * * ?") // Cron表达式
public void cronTask() {
// 任务代码
}
TaskScheduler方式
@Autowired
private TaskScheduler taskScheduler;
// Cron触发器
taskScheduler.schedule(
() -> { /* 任务代码 */ },
new CronTrigger("0/10 * * * * ?")
);
// 固定延迟触发器
taskScheduler.scheduleWithFixedDelay(
() -> { /* 任务代码 */ },
TimeUnit.SECONDS.toMillis(30)
);
//如定时发送心跳检测
public void startHeartbeatCheck() {
taskScheduler.scheduleWithFixedDelay(
() -> {
try {
performHeartbeatCheck();
} catch (Exception e) {
log.error("心跳检测失败", e);
}
},
TimeUnit.SECONDS.toMillis(30) // 每30秒执行一次
);
}
### 配置说明
1. 启用定时任务
```java
@Configuration
@EnableScheduling
public class SchedulerConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5);
scheduler.setThreadNamePrefix("scheduled-task-");
return scheduler;
}
}
适用场景:
处理复杂的异步任务链(如订单处理流程)
需要组合多个异步操作的结果(如用户数据聚合)
事件驱动型的异步处理
需要细粒度控制线程行为和异常处理
使用回调方式与netty相似
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat(“guava-pool-%d”)
.setDaemon(true)
.setPriority(Thread.NORM_PRIORITY)
.setUncaughtExceptionHandler((thread, ex) ->
log.error(“Thread error: {}”, thread.getName(), ex))
.build();
ListeningExecutorService service = MoreExecutors.listeningDecorator(
new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(1000),
threadFactory));
// 使用方式
ListenableFuture future = service.submit(task);
Futures.addCallback(future, new FutureCallback() {
public void onSuccess(Result result) { … }
public void onFailure(Throwable t) { … }
});
一、订单处理流程
private final ListeningExecutorService guavaExecutor;
public ThirdPartyThreadPoolExample() {
// 初始化Guava线程池
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat("business-process-pool-%d")
.setDaemon(true)
.setPriority(Thread.NORM_PRIORITY)
.setUncaughtExceptionHandler((thread, ex) ->
log.error("业务处理线程异常: {}", thread.getName(), ex))
.build();
guavaExecutor = MoreExecutors.listeningDecorator(
new ThreadPoolExecutor(5, 20,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000),
threadFactory,
new ThreadPoolExecutor.CallerRunsPolicy()));
}
public void processOrders(List orders) {
List> futures = orders.stream()
.map(order -> guavaExecutor.submit(() -> processOrder(order)))
.collect(Collectors.toList());
// 批量处理订单结果
ListenableFuture> allFutures = Futures.allAsList(futures);
Futures.addCallback(allFutures, new FutureCallback<>() {
@Override
public void onSuccess(List results) {
// 批量更新订单状态
updateOrderStatuses(results);
// 发送通知
sendNotifications(results);
}
@Override
public void onFailure(Throwable t) {
log.error("批量订单处理失败", t);
// 处理失败情况
handleBatchProcessingFailure(orders);
}
}, guavaExecutor);
}
二、异步数据聚合
public void aggregateUserData(String userId) {
// 并行获取用户各种数据
ListenableFuture profileFuture = guavaExecutor.submit(() -> getUserProfile(userId));
ListenableFuture> ordersFuture = guavaExecutor.submit(() -> getUserOrders(userId));
ListenableFuture creditFuture = guavaExecutor.submit(() -> getUserCredit(userId));
// 组合多个异步结果
ListenableFuture aggregateFuture = Futures.whenAllComplete(
profileFuture, ordersFuture, creditFuture)
.call(() -> {
return new UserAggregateData(
profileFuture.get(),
ordersFuture.get(),
creditFuture.get()
);
}, guavaExecutor);
// 处理最终的聚合结果
Futures.addCallback(aggregateFuture,
new FutureCallback() {
@Override
public void onSuccess(UserAggregateData data) {
updateUserDashboard(data);
}
@Override
public void onFailure(Throwable t) {
log.error("用户数据聚合失败: {}", userId, t);
}
}, guavaExecutor);
}
可用于自定义线程池时简化步骤
// 创建
ExecutorService executor = ThreadUtil.newExecutor(2, 4);
// 执行异步任务
ThreadUtil.execute(() -> {
// 任务代码
});
// 创建定时任务
CronUtil.schedule("*/2 * * * * *", (Task) () -> {
// 任务代码
});
适用场景:
管理重量级资源对象(如数据库连接)
管理网络连接(如Netty客户端连接)
需要精确控制资源池大小和行为的场景
需要对资源进行复用和生命周期管理
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(10);
config.setMaxIdle(5);
ObjectPool pool = new GenericObjectPool<>(
new MyPoolableObjectFactory(), config);
// 使用连接
Connection conn = pool.borrowObject();
try {
// 使用连接
} finally {
pool.returnObject(conn);
}
一、数据库连接管理
private final GenericObjectPool connectionPool;
public ThirdPartyThreadPoolExample() {
// 初始化数据库连接池配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMaxTotal(20);
poolConfig.setMaxIdle(10);
poolConfig.setMinIdle(5);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestWhileIdle(true);
poolConfig.setTimeBetweenEvictionRuns(Duration.ofMinutes(1));
poolConfig.setMinEvictableIdleTime(Duration.ofMinutes(5));
connectionPool = new GenericObjectPool<>(new DatabaseConnectionFactory(), poolConfig);
}
public void performDatabaseOperations(String sql) throws Exception {
DatabaseConnection conn = null;
try {
conn = connectionPool.borrowObject();
conn.executeQuery(sql);
} finally {
if (conn != null) {
connectionPool.returnObject(conn);
}
}
}
// Apache Commons Pool示例2:批量数据处理
public void processBatchData(List dataItems) throws Exception {
List connections = new ArrayList<>();
try {
// 获取多个连接用于并行处理
for (int i = 0; i < Math.min(dataItems.size(), 5); i++) {
connections.add(connectionPool.borrowObject());
}
// 使用连接池中的连接并行处理数据
ExecutorService executor = Executors.newFixedThreadPool(connections.size());
List> futures = new ArrayList<>();
for (int i = 0; i < connections.size(); i++) {
DatabaseConnection conn = connections.get(i);
List batch = getBatch(dataItems, i, connections.size());
futures.add(CompletableFuture.runAsync(() -> {
try {
processBatch(conn, batch);
} catch (Exception e) {
log.error("批处理失败", e);
throw new RuntimeException(e);
}
}, executor));
}
// 等待所有批处理完成
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
executor.shutdown();
} finally {
// 归还所有连接
for (DatabaseConnection conn : connections) {
connectionPool.returnObject(conn);
}
}
}
二、netty客户端连接
private final GenericObjectPool channelConnectPool;
channelConnectPool = new GenericObjectPool<>(new NettyClientConnectionFactory());
public void manageNettyConnections() throws Exception {
NettyClientConnection conn = null;
try {
conn = channelConnectPool.borrowObject();
conn.sendData("业务消息");
} finally {
if (conn != null) {
channelConnectPool.returnObject(conn);
}
}
}