项目场景:
在开发中、我们经常会碰到一个工程中会用到多个线程池,在代码中、我们大多会在当前业务代码里直接创建线程池,如果有多个功能去创建多个线程池、在不同地方是不方便我们管理的、其他开发同事也并不会对每个业务很熟悉、在开发时便会有不必要的工时浪费。
那么我们如何优雅的管理线程池呢?
解决方案:
创建线程池核心参数抽象类
@Data
public abstract class AbstractExecutorPool {
// 核心线程数
private int coreSize;
// 最大线程数
private int maxSize;
// 当线程数大于核心线程时,这是多余的空闲线程在终止前等待新任务的最长时间(默认核心线程不会退出)
private int keepAlive;
// 消息队列
private int queueCapacity;
}
创建实现类、这里继承线程池参数抽象类
@Data
@ConfigurationProperties(prefix = "thread-pool.download")
@Component
public class DownloadThreadPool extends AbstractExecutorPool{
}
@Data
@ConfigurationProperties(prefix = "thread-pool.upload")
@Component
public class UploadThreadPool extends AbstractExecutorPool{
}
nacos配置、这里配置了线程池核心的参数
# 线程池配置
thread-pool:
# 测试用线程池1
download:
coreSize: 2
maxSize: 4
keepAlive: 100
queueCapacity: 10
# 测试用线程池2
upload:
coreSize: 3
maxSize: 6
keepAlive: 200
queueCapacity: 4
创建线程池管理类、initThreadPool为通用线程池代码、可根据不同传入不同参数创建不同线程池
@Configuration
@EnableAsync
@Slf4j
public class ThreadPoolManager {
// 下载用线程池
private DownloadThreadPool downloadThreadPool;
// 上传用线程池
private uploadThreadPool uploadThreadPool;
@Autowired
public ThreadPoolManager(DownloadThreadPool downloadThreadPool, uploadThreadPool uploadThreadPool) {
this.downloadThreadPool= downloadThreadPool;
this.uploadThreadPool= uploadThreadPool;
}
/**
* 创建线程池 用于处理下载(这里示例没有回调方法)
*/
public ThreadPoolExecutor asyncExecutorDownload() {
// 这里是自定义策略、可以根据不同业务使用不同策略
CustomRejectedExecutionHandler customRejectedExecutionHandler = new CustomRejectedExecutionHandler();
return initThreadPool(downloadThreadPool, customRejectedExecutionHandler, null);
}
/**
* 创建线程池 用于处理上传(这里示例有回调方法)
*/
public ThreadPoolExecutor asyncExecutorUpload(Callable<?> callable) {
// 这里是自定义策略、可以根据不同业务使用不同策略
CustomRejectedExecutionHandler customRejectedExecutionHandler = new CustomRejectedExecutionHandler();
return initThreadPool(uploadThreadPool, customRejectedExecutionHandler, callable);
}
/**
* 初始化线程池
*
* @param abstractExecutorPool 线程池参数
* @param rejectedExecutionHandler 策略
* @param callable 线程池回调方法
* @return
*/
private ThreadPoolExecutor initThreadPool(AbstractExecutorPool abstractExecutorPool, RejectedExecutionHandler rejectedExecutionHandler, Callable<?> callable) {
return new ThreadPoolExecutor(
abstractExecutorPool.getCoreSize(), // 核心线程数
abstractExecutorPool.getMaxSize(), // 最大线程数
abstractExecutorPool.getKeepAlive(),
TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<>(abstractExecutorPool.getQueueCapacity()),
Executors.defaultThreadFactory(),
rejectedExecutionHandler) {
@Override
protected void terminated() {
if (callable != null) {
try {
callable.call();
} catch (Exception e) {
log.error("线程池所有任务结束后回调异常", e);
}
}
}
};
}
}
创建线程池
// 创建线程池(上传,有回调)
ThreadPoolExecutor uploadThreadPool = threadPoolConfig.asyncExecutorUpload(() -> {
log.info("========this is callBack========");
return null;
}
);
for (int i = 0; i < 10; i++) {
uploadThreadPool.execute(() ->
log.info("========this is upload process========");
);
}
// 创建线程池(下载,无回调)
ThreadPoolExecutor downloadThreadPool = threadPoolConfig.asyncExecutordownload();
for (int i = 0; i < 10; i++) {
downloadThreadPool.execute(() ->
log.info("========this is download process========");
);
}
总结:
定义线程核心配置抽象类、创建线程池管理类、封装创建线程池通用方法,不同业务创建线程池只需调用通用初始化方法、传入线程池策略、回调等即可