代码
代码类结构
- ThreadPoolMonitor:线程池扩展类
- ThreadPoolUtil:线程池工具类
- ThreadPoolDetailInfo:bean类
- ExecutorThreadPoolManager:线程池实现类
- ThreadPoolController:线程池测试方法
线程池扩展类
- 从类主要重写了ThreadPoolExecutor类中的shutdown/shutdownNow/beforeExecute/afterExecute,用于对每个任务进行执行前后的拦截,计算出每个任务的运行时间。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
/**
* @ClassName ThreadPoolMonitor
* @desc 线程池扩展类
* @authors ruicm
* @Date 2023/12/04 19:45
**/
public class ThreadPoolMonitor extends ThreadPoolExecutor {
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolMonitor.class);
private final ConcurrentHashMap<String, Date> startTimes;
private final String poolName;
private long totalDiff;
public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, String poolName) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
this.startTimes = new ConcurrentHashMap();
this.poolName = poolName;
}
@Override
public void shutdown() {
LOGGER.info("{} Going to shutdown. Executed tasks: {}, Running tasks: {}, Pending tasks: {}", new Object[]{this.poolName, this.getCompletedTaskCount(), this.getActiveCount(), this.getQueue().size()});
super.shutdown();
}
@Override
public List<Runnable> shutdownNow() {
LOGGER.info("{} Going to immediately shutdown. Executed tasks: {}, Running tasks: {}, Pending tasks: {}", new Object[]{this.poolName, this.getCompletedTaskCount(), this.getActiveCount(), this.getQueue().size()});
return super.shutdownNow();
}
@Override
protected void beforeExecute(Thread t, Runnable r) {
this.startTimes.put(String.valueOf(r.hashCode()), new Date());
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
Date startDate = this.startTimes.remove(String.valueOf(r.hashCode()));
Date finishDate = new Date();
long diff = finishDate.getTime() - startDate.getTime();
this.totalDiff += diff;
}
public long getTotalDiff() {
return this.totalDiff;
}
}
线程工具类
import cn.*.ThreadPoolMonitor;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
* @ClassName ThreadPoolUtil
* @authors ruicm
* @Date 2023/12/04 19:45
**/
@Component
public class ThreadPoolUtil {
private final HashMap<String, ThreadPoolMonitor> threadPoolExecutorHashMap = new HashMap();
public ThreadPoolUtil() {
}
public ThreadPoolMonitor creatThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,String poolName) {
ThreadPoolMonitor threadPoolExecutor = new ThreadPoolMonitor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,threadFactory, poolName);
this.threadPoolExecutorHashMap.put(poolName, threadPoolExecutor);
return threadPoolExecutor;
}
public HashMap<String, ThreadPoolMonitor> getThreadPoolExecutorHashMap() {
return this.threadPoolExecutorHashMap;
}
}
线程bean类
import lombok.Data;
@Data
public class ThreadPoolDetailInfo {
//线程池名字
private String threadPoolName;
//当前线程池大小
private Integer poolSize;
//线程池核心线程数量
private Integer corePoolSize;
//线程池生命周期中最大线程数量
private Integer largestPoolSize;
//线程池中允许的最大线程数
private Integer maximumPoolSize;
//线程池完成的任务数目
private long completedTaskCount;
//线程池中当前活跃个数
private Integer active;
//线程池完成的任务个数
private long task;
//线程最大空闲时间
private long keepAliveTime;
//当前活跃线程的占比
private int activePercent;
//任务队列容量(阻塞队列)
private Integer queueCapacity;
//当前队列中任务的数量
private Integer queueSize;
//线程池中任务平均执行时长
private long avgExecuteTime;
public ThreadPoolDetailInfo(String threadPoolName, Integer poolSize, Integer corePoolSize, Integer largestPoolSize, Integer maximumPoolSize, long completedTaskCount, Integer active, long task, long keepAliveTime, int activePercent, Integer queueCapacity, Integer queueSize, long avgExecuteTime) {
this.threadPoolName = threadPoolName;
this.poolSize = poolSize;
this.corePoolSize = corePoolSize;
this.largestPoolSize = largestPoolSize;
this.maximumPoolSize = maximumPoolSize;
this.completedTaskCount = completedTaskCount;
this.active = active;
this.task = task;
this.keepAliveTime = keepAliveTime;
this.activePercent = activePercent;
this.queueCapacity = queueCapacity;
this.queueSize = queueSize;
this.avgExecuteTime = avgExecuteTime;
}
}
线程池实现类
- 在我的项目中,将线程池依次划分为high、normal、low、single四种线程池类型。不同优先级的任务将会被submit到不同的线程池中执行。
- 在业务中有判断线程池中queue的长度来决定是否投递任务,由于没有相应的拒绝策略,所以队列不设置长度。
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.*.ThreadPoolUtil;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Component
public class ExecutorThreadPoolManager {
@Autowired
private ThreadPoolUtil threadPoolUtil;
@Value("${thread.pool.normal.level.thread.max-num}")
private Integer normalLevelThreadPoolThreadMaxNum;
@Value("${thread.pool.normal.level.core.thread-num}")
private Integer normalLevelThreadPoolCoreThreadNum;
@Value("${thread.pool.low.level.thread.max-num}")
private Integer lowLevelThreadPoolThreadMaxNum;
@Value("${thread.pool.low.level.core.thread-num}")
private Integer lowLevelThreadPoolCoreThreadNum;
private ThreadPoolExecutor normalThreadPoolExecutor;
private ThreadPoolExecutor highPriorityExecutor;
private ThreadPoolExecutor lowPriorityExecutor;
private ThreadPoolExecutor singleThreadPoolExecutor;
@PostConstruct
public void initExecutor() {
ThreadFactory normalThreadFactory = new ThreadFactoryBuilder().setNameFormat("normal_task_thread_%d").build();
normalThreadPoolExecutor = threadPoolUtil.creatThreadPool(normalLevelThreadPoolCoreThreadNum, normalLevelThreadPoolThreadMaxNum, 0L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), normalThreadFactory,"normal_level_thread_pool");
ThreadFactory highPriorityThreadFactory = new ThreadFactoryBuilder().setNameFormat("high_priority_level_task_thread_%d").build();
highPriorityExecutor = threadPoolUtil.creatThreadPool(normalLevelThreadPoolCoreThreadNum, normalLevelThreadPoolThreadMaxNum, 0L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), highPriorityThreadFactory,"high_level_thread_pool");
ThreadFactory lowPriorityThreadFactory = new ThreadFactoryBuilder().setNameFormat("low_priority_level_task_thread_%d").build();
lowPriorityExecutor = threadPoolUtil.creatThreadPool(lowLevelThreadPoolCoreThreadNum, lowLevelThreadPoolThreadMaxNum, 0L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), lowPriorityThreadFactory,"low_level_thread_pool");
ThreadFactory singleFactory = new ThreadFactoryBuilder().setNameFormat("single_task_thread_%d").build();
singleThreadPoolExecutor =threadPoolUtil.creatThreadPool(1, 1,
0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), singleFactory,"single_level_thread_pool");
}
/**
* @author ruicm
* @date 2023/12/05
* @describe 定义三种线程池, 一般采集类的用低优, 正常业务的用中优, 用户手动请求API的用高优线程池
**/
public ThreadPoolExecutor getNormalThreadPoolExecutor() {
return normalThreadPoolExecutor;
}
public ThreadPoolExecutor getHighPriorityExecutor() {
return highPriorityExecutor;
}
public ThreadPoolExecutor getLowPriorityExecutor() {
return lowPriorityExecutor;
}
public ThreadPoolExecutor getSingleThreadPoolExecutor() {
return singleThreadPoolExecutor;
}
线程池监控接口类
运行结果
- 上面controller中的方法除了可以通过接口进行暴露外,还设置了定时任务定期的打印到日志中。方便对系统状态进行排查。
[
{
"threadPoolName": "high_level_thread_pool",
"poolSize": 0,
"corePoolSize": 10,
"largestPoolSize": 0,
"maximumPoolSize": 20,
"completedTaskCount": 0,
"active": 0,
"task": 0,
"keepAliveTime": 0,
"activePercent": 0,
"queueCapacity": 0,
"queueSize": 0,
"avgExecuteTime": 0
},
{
"threadPoolName": "low_level_thread_pool",
"poolSize": 0,
"corePoolSize": 15,
"largestPoolSize": 0,
"maximumPoolSize": 15,
"completedTaskCount": 0,
"active": 0,
"task": 0,
"keepAliveTime": 0,
"activePercent": 0,
"queueCapacity": 0,
"queueSize": 0,
"avgExecuteTime": 0
},
{
"threadPoolName": "normal_level_thread_pool",
"poolSize": 0,
"corePoolSize": 10,
"largestPoolSize": 0,
"maximumPoolSize": 20,
"completedTaskCount": 0,
"active": 0,
"task": 0,
"keepAliveTime": 0,
"activePercent": 0,
"queueCapacity": 0,
"queueSize": 0,
"avgExecuteTime": 0
},
{
"threadPoolName": "single_level_thread_pool",
"poolSize": 0,
"corePoolSize": 1,
"largestPoolSize": 0,
"maximumPoolSize": 1,
"completedTaskCount": 0,
"active": 0,
"task": 0,
"keepAliveTime": 0,
"activePercent": 0,
"queueCapacity": 0,
"queueSize": 0,
"avgExecuteTime": 0
}
]