一、ThreadPool
1
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PreDestroy;
import java.util.concurrent.*;
@Configuration
public class ThreadPoolConfig {
//使用 destroyMethod = "shutdown" 可让 Spring 容器关闭时自动调用 shutdown()。 生产不推荐
private ThreadPoolExecutor executor;
@Bean("cpuPoolExecutor")
public ThreadPoolExecutor customTaskExecutor() {
int corePoolSize = 4;
int maxPoolSize = 4;
long keepAliveTime = 60L;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(100);
ThreadFactory threadFactory = Executors.defaultThreadFactory();
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
return new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
workQueue,
threadFactory,
handler
);
}
// 强烈建议通过 @PreDestroy 优雅关闭
@PreDestroy
public void shutdownExecutor() {
if (executor != null) {
System.out.println("Shutting down custom thread pool...");
executor.shutdown();
try {
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
System.err.println("Thread pool did not terminate gracefully");
}
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
}
2
package com.example.service;
import com.example.entity.Req.ThreadReq;
public interface ThreadPoolService {
void fetchAllData1(ThreadReq param);
void fetchAllData2(ThreadReq param);
}
3、
package com.example.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.example.entity.Address;
import com.example.entity.Category;
import com.example.entity.Req.ThreadReq;
import com.example.entity.User;
import com.example.service.AddressService;
import com.example.service.CategoryService;
import com.example.service.ThreadPoolService;
import com.example.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
@Service
public class ThreadPoolServiceImpl implements ThreadPoolService {
Logger logger = LoggerFactory.getLogger(ThreadPoolServiceImpl.class);
@Qualifier("cpuPoolExecutor")
@Autowired
ThreadPoolExecutor cpuPoolExecutor;
@Autowired
UserService userService;
@Autowired
CategoryService categoryService;
@Autowired
AddressService addressService;
@Override
public void fetchAllData1(ThreadReq param) {
CompletableFuture<List<User>> userFuture = CompletableFuture
.supplyAsync(() -> {
try {
logger.info("---getUserList() call start");
return userService.getUserList(param.getName());
} catch (Exception e) {
logger.error("fetchAllData1(): getUserList() error:{}",e.getMessage(),e);
return new ArrayList<>();
}
}, cpuPoolExecutor);
CompletableFuture<List<Category>> categoryFuture = CompletableFuture
.supplyAsync(() -> {
try {
return categoryService.getCategoryList();
} catch (Exception e) {
logger.error("getCategoryList() error", e);
return new ArrayList<>(); // 空列表
}
}, cpuPoolExecutor);
CompletableFuture<Address> addressFuture = CompletableFuture
.supplyAsync(() -> {
try {
return addressService.getAddress(param.getId());
} catch (Exception e) {
logger.error("getAddress() error:", e);
return null;
}
}, cpuPoolExecutor);
// 2. ⭐ 关键:等待所有任务完成(阻塞当前线程,直到全部结束)
CompletableFuture<Void> allDone = CompletableFuture.allOf(
userFuture, categoryFuture, addressFuture
);
allDone.join(); // 阻塞,直到全部完成(即使有异常也不会抛出,因为我们用了 exceptionally)
// 3. 获取结果(此时不会阻塞,且不会抛异常)
List<User> users = userFuture.getNow(new ArrayList<>());
List<Category> categories = categoryFuture.getNow(new ArrayList<>());
Address address = addressFuture.getNow(null);
// 4. ✅ 在本方法内处理结果(全部完成后才执行)
logger.info("users={}", JSONObject.toJSONString(users));
logger.info("categories={}", JSONObject.toJSONString(categories));
logger.info("address={}", JSONObject.toJSONString(address));
}
@Override
public void fetchAllData2(ThreadReq param) {
// 每个任务内部捕获异常,返回 null 或默认值
// 提交任务
Future<List<User>> userFuture = cpuPoolExecutor.submit(() -> {
try {
return userService.getUserList(param.getName());
} catch (Exception e) {
throw new ExecutionException("Failed to fetch user info", e);
}
});
Future<List<Category>> categoryFuture = cpuPoolExecutor.submit(() -> {
try {
return categoryService.getCategoryList();
} catch (Exception e) {
throw new ExecutionException("Failed to fetch user info", e);
}
});
Future<Address> addressFuture = cpuPoolExecutor.submit(() -> {
try {
return addressService.getAddress(param.getId());
} catch (Exception e) {
throw new ExecutionException("Failed to fetch user info", e);
}
});
// 设置超时时间(避免无限等待)
long timeout = 10L;
List<User> userList = getWithTimeout(userFuture, "User Info", timeout,TimeUnit.SECONDS);
List<Category> categoryList = getWithTimeout(categoryFuture, "User Info", timeout,TimeUnit.SECONDS);
Address address = getWithTimeout(addressFuture, "User Info", timeout,TimeUnit.SECONDS);
logger.info("userList={}",JSONObject.toJSONString(userList));
logger.info("categoryList={}",JSONObject.toJSONString(categoryList));
logger.info("address={}",JSONObject.toJSONString(address));
}
/**
* 通用方法:安全获取 Future 的结果,支持任意返回类型 T
*
* @param future Future<T> 任务
* @param taskName 任务名称(用于日志)
* @param timeout 超时时间数值
* @param unit 时间单位
* @param <T> 返回值泛型类型
* @return 成功则返回 T,失败或异常返回 null
*/
private <T> T getWithTimeout(Future<T> future, String taskName, long timeout, TimeUnit unit) {
try {
return future.get(timeout, unit);
} catch (TimeoutException e) {
future.cancel(true); // 中断正在执行的线程
System.err.println("【超时】" + taskName + " 执行超时 (" + timeout + " " + unit + ")");
return null;
} catch (ExecutionException e) {
// 业务代码抛出的异常(如 NullPointerException、IllegalArgumentException)
Throwable cause = e.getCause();
System.err.println("【业务异常】" + taskName + " 异常: " + cause.getClass().getSimpleName() + " - " + cause.getMessage());
return null;
} catch (InterruptedException e) {
// 当前线程被中断(比如容器关闭)
Thread.currentThread().interrupt();
System.err.println("【中断】" + taskName + " 被中断");
return null;
} catch (CancellationException e) {
// 任务已被取消(可能是超时后 cancel(true) 导致)
System.err.println("【取消】" + taskName + " 已被取消");
return null;
}
}
}
二、
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
public class ThreadPoolTaskConfig {
@Bean("cpuTaskExecutor")
public ThreadPoolTaskExecutor cpuTaskExecutor() {
//CPU 密集型任务: corePoolSize = maxPoolSize = CPU 核心数 + 1(或直接等于 CPU 核心数)
// IO 密集型:核心线程数设为 CPU 核心数的 4~8 倍
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4); // 核心线程数
executor.setMaxPoolSize(4); // 最大线程数
executor.setQueueCapacity(100); // 队列容量
executor.setThreadNamePrefix("CPUThread-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略
executor.initialize();
return executor;
}
@Bean("ioTaskExecutor")
public ThreadPoolTaskExecutor ioTaskExecutor() {
//CPU 密集型任务: corePoolSize = maxPoolSize = CPU 核心数 + 1(或直接等于 CPU 核心数)
// IO 密集型:核心线程数设为 CPU 核心数的 4~8 倍
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(16); // 核心线程数 // 4 * 4
executor.setMaxPoolSize(32); // 最大线程数 // 4 * 8
executor.setQueueCapacity(100); // 队列容量
executor.setThreadNamePrefix("IOThread-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略
executor.initialize();
return executor;
}
}
2、
package com.example.service;
import com.example.entity.Req.ThreadReq;
public interface ThreadTaskPoolService {
void fetchAllData(ThreadReq param);
void fetchAllData2(ThreadReq param);
}
package com.example.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.example.entity.Address;
import com.example.entity.Category;
import com.example.entity.Req.ThreadReq;
import com.example.entity.User;
import com.example.service.AddressService;
import com.example.service.CategoryService;
import com.example.service.ThreadTaskPoolService;
import com.example.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Service
public class ThreadTaskPoolServiceImpl implements ThreadTaskPoolService {
Logger logger = LoggerFactory.getLogger(ThreadTaskPoolServiceImpl.class);
@Autowired
@Qualifier("cpuTaskExecutor")
ThreadPoolTaskExecutor cpuTaskExecutor;
@Autowired
UserService userService;
@Autowired
CategoryService categoryService;
@Autowired
AddressService addressService;
@Override
public void fetchAllData(ThreadReq param) {
// 每个任务内部捕获异常,返回 null 或默认值
CompletableFuture<List<User>> userFuture = CompletableFuture
.supplyAsync(() -> {
try {
return userService.getUserList(param.getName());
} catch (Exception e) {
logger.error("fetchAllData(): getUserList() error:{}",e.getMessage(),e);
return null; // 或 new User("default", "未知用户")
}
}, cpuTaskExecutor);
CompletableFuture<List<Category>> categoryFuture = CompletableFuture
.supplyAsync(() -> {
try {
return categoryService.getCategoryList();
} catch (Exception e) {
logger.warn("getCategoryList() error", e);
return new ArrayList<>(); // 空列表
}
}, cpuTaskExecutor);
CompletableFuture<Address> addressFuture = CompletableFuture
.supplyAsync(() -> {
try {
return addressService.getAddress(param.getId());
} catch (Exception e) {
logger.error("getAddress() error:", e);
return null;
}
}, cpuTaskExecutor);
// 2. ⭐ 关键:等待所有任务完成(阻塞当前线程,直到全部结束)
CompletableFuture<Void> allDone = CompletableFuture.allOf(
userFuture, categoryFuture, addressFuture
);
allDone.join(); // 阻塞,直到全部完成(即使有异常也不会抛出,因为我们用了 exceptionally)
// 3. 获取结果(此时不会阻塞,且不会抛异常)
List<User> users = userFuture.getNow(new ArrayList<>());
List<Category> categories = categoryFuture.getNow(new ArrayList<>());
Address address = addressFuture.getNow(null);
// 4. ✅ 在本方法内处理结果(全部完成后才执行)
logger.info("users={}", JSONObject.toJSONString(users));
logger.info("categories={}", JSONObject.toJSONString(categories));
logger.info("address={}", JSONObject.toJSONString(address));
}
@Override
public void fetchAllData2(ThreadReq param) {
}
}