一、概述
1、提供对线程池核心参数及运行的状态的监控,如核心队列的大小,活跃线程池数,线程池最多核心数等做监控和告警
2、支持在Apollo上动态修改核心线程数(corePoolSize)和最大线程数(maxNumPoolSize)和线程活跃时间(keepAliveTime)
二、使用方法
2.1坐标引用
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.5.9</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.5.9</version>
</dependency>
2.2配置开关
开启开关,会收集线程池的监控数据
# 开启线程池监控 默认为true
sc.thread.pool.metrics.enabled=true
2.3 使用封装类创建线程池
封装了一些常用的线程池类,要加入监控和Apollo,必须使用这些类去创建线程池。主要是针对原来的executor加了命名,参数比Executor多了名称,其他不变。
com.cxytiandi.threadpool.NamedExecutors
com.cxytiandi.threadpool.NamedExecutor
com.cxytiandi.threadpool.NamedScheduledThreadPoolExecutor
2.4 动态修改线程池
对线程池做了动态修改的封装,可以支持在Apollo上面动态修改核心线程数(corePoolSize)和最大核心线程数(maxinumPoolSize)和线程存活时间(keepAliveTime)
#核心线程数
sc.thread.pool.线程池名称.corePoolSize=10
#最大线程数
sc.thread.pool.线程池名称.maxinumPoolSize=10
#存活时间
sc.thread.pool.线程池名称.keepAliveTime=10
2.4 设计方案
1、通过自定义线程池类,如NamedExecutors,在创建线程池的时候将线程池添加到ThreadPoolManager中
2、通过ThreadPoolManager可以获取到添加的线程集合
3、通过获取到的集合实现监控和修改
#启动配置类
com.cxytiandi.threadpool.autoConfig.ThreadPoolMetricsAutoConfiguration
#Apollo动态修改类
com.cxytiandi.threadpool.rebinder.ThreadPoolExecutorRebinder
#监控推送类
com.cxytiandi.threadpool.metrics.ThreadPoolMetrics
#线程池管理类
com.cxytiandi.threadpool.ThreadPoolManager
#若引用,防止内存溢出
com.cxytiandi.threadpool.SoftReferenceMap
2.5 服务监控
注意: 线程池命名不要带“*”;默认会注入spring托管的线程池,如果线程池没有实现NamedExecutor,线程池名称就没有绑定,所以名称回事该对象的hashCode
2.6 代码实现
ThreadPoolMetricsAutoConfiguration
package com.cxytiandi.threadpool.autoConfig;
import com.cxytiandi.threadpool.ThreadPoolManager;
import com.cxytiandi.threadpool.metrics.ThreadPoolMetrics;
import com.cxytiandi.threadpool.rebinder.ThreadPoolExecutorRebinder;
import io.micrometer.core.instrument.MeterRegistry;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @ClassName: ThreadPoolMetricsAutoConfiguration
* @Description:
* @Author: Administrator
* @Date: 2023-12-10 14:04
* @Version:1.0
*/
@Configuration
@ConditionalOnProperty(value = "sc.thread.pool.metrics.enabled",matchIfMissing = true)
public class ThreadPoolMetricsAutoConfiguration implements InitializingBean {
@Autowired(required = false)
private List<ThreadPoolExecutor> threadPoolExecutorList;
@Override
public void afterPropertiesSet() throws Exception {
if(CollectionUtils.isNotEmpty(threadPoolExecutorList)){
for (ThreadPoolExecutor threadPoolExecutor : threadPoolExecutorList) {
ThreadPoolManager.addThreadPoolExecutor(threadPoolExecutor);
}
}
}
@Bean
@ConditionalOnClass(MeterRegistry.class)
public ThreadPoolMetrics threadPoolMetrics(){
ThreadPoolMetrics threadPoolMetrics = new ThreadPoolMetrics();
return threadPoolMetrics;
}
@Bean
@ConditionalOnClass(value = EnvironmentChangeEvent.class)
public ThreadPoolExecutorRebinder threadPoolExecutorRebinder(){
ThreadPoolExecutorRebinder threadPoolExecutorRebinder = new ThreadPoolExecutorRebinder();
return threadPoolExecutorRebinder;
}
}
ThreadPoolMetrics
package com.cxytiandi.threadpool.metrics;
import com.cxytiandi.threadpool.NamedExecutor;
import com.cxytiandi.threadpool.NamedExecutors;
import com.cxytiandi.threadpool.ThreadPoolManager;
import com.google.common.collect.Lists;
import io.micrometer.core.instrument.ImmutableTag;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.binder.MeterBinder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.DisposableBean;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @ClassName: ThreadPoolMetrics
* @Description: 接入监控
* @Author: Administrator
* @Date: 2023-12-10 12:58
* @Version:1.0
*/
@Slf4j
public class ThreadPoolMetrics implements MeterBinder,DisposableBean {
private ScheduledExecutorService scheduledExecutorService = NamedExecutors.newScheduleThreadPool("threadPoolMetrics",1);
/**
* 初始化的时候,会注册一次,以后不会调用
* @param meterRegistry
*/
@Override
public void bindTo(MeterRegistry meterRegistry) {
Set<ThreadPoolExecutor> threadPoolExecutors = ThreadPoolManager.getThreadPoolExecutors();
scheduledExecutorService.scheduleAtFixedRate(()->addMetrics(meterRegistry,threadPoolExecutors),60,60, TimeUnit.SECONDS);
}
private void addMetrics(MeterRegistry meterRegistry, Set<ThreadPoolExecutor> threadPoolExecutorSet) {
if(null == threadPoolExecutorSet || threadPoolExecutorSet.size() == 0){
return;
}
for (ThreadPoolExecutor threadPoolExecutor : threadPoolExecutorSet) {
String name = null;
if(threadPoolExecutor instanceof NamedExecutor){
name = ((NamedExecutor)threadPoolExecutor).getName();
}else {
name = threadPoolExecutor.hashCode() + StringUtils.EMPTY; // 通过HashCode区分
}
// 设置核心线程池
registerCoreSize(meterRegistry,threadPoolExecutor,name);
registerMaxSize(meterRegistry,threadPoolExecutor,name);
registerPoolSize(meterRegistry,threadPoolExecutor,name);
registerQueueSize(meterRegistry,threadPoolExecutor,name);
registerActiveSize(meterRegistry,threadPoolExecutor,name);
registerCompletedSize(meterRegistry,threadPoolExecutor,name);
}
}
private void registerCompletedSize(MeterRegistry meterRegistry, ThreadPoolExecutor threadPoolExecutor, String name) {
List<Tag> tagList = Lists.newArrayList();
Tag tag1 = new ImmutableTag("name", name);
Tag tag2 = new ImmutableTag("type", "completedCount");
tagList.add(tag1);
tagList.add(tag2);
meterRegistry.gauge("thread.pool.metrics",tagList,threadPoolExecutor,value -> threadPoolExecutor.getCompletedTaskCount());
}
private void registerActiveSize(MeterRegistry meterRegistry, ThreadPoolExecutor threadPoolExecutor, String name) {
List<Tag> tagList = Lists.newArrayList();
Tag tag1 = new ImmutableTag("name", name);
Tag tag2 = new ImmutableTag("type", "activeCount");
tagList.add(tag1);
tagList.add(tag2);
meterRegistry.gauge("thread.pool.metrics",tagList,threadPoolExecutor,value -> threadPoolExecutor.getActiveCount());
}
private void registerQueueSize(MeterRegistry meterRegistry, ThreadPoolExecutor threadPoolExecutor, String name) {
List<Tag> tagList = Lists.newArrayList();
Tag tag1 = new ImmutableTag("name", name);
Tag tag2 = new ImmutableTag("type", "queueSize");
tagList.add(tag1);
tagList.add(tag2);
meterRegistry.gauge("thread.pool.metrics",tagList,threadPoolExecutor,value -> threadPoolExecutor.getQueue().size());
}
private void registerPoolSize(MeterRegistry meterRegistry, ThreadPoolExecutor threadPoolExecutor, String name) {
List<Tag> tagList = Lists.newArrayList();
Tag tag1 = new ImmutableTag("name", name);
Tag tag2 = new ImmutableTag("type", "poolSize");
tagList.add(tag1);
tagList.add(tag2);
meterRegistry.gauge("thread.pool.metrics",tagList,threadPoolExecutor,value -> threadPoolExecutor.getPoolSize());
}
private void registerMaxSize(MeterRegistry meterRegistry, ThreadPoolExecutor threadPoolExecutor, String name) {
List<Tag> tagList = Lists.newArrayList();
Tag tag1 = new ImmutableTag("name", name);
Tag tag2 = new ImmutableTag("type", "maxSize");
tagList.add(tag1);
tagList.add(tag2);
meterRegistry.gauge("thread.pool.metrics",tagList,threadPoolExecutor,value -> threadPoolExecutor.getMaximumPoolSize());
}
private void registerCoreSize(MeterRegistry meterRegistry, ThreadPoolExecutor threadPoolExecutor, String name) {
List<Tag> tagList = Lists.newArrayList();
Tag tag1 = new ImmutableTag("name", name);
Tag tag2 = new ImmutableTag("type", "coreSize");
tagList.add(tag1);
tagList.add(tag2);
meterRegistry.gauge("thread.pool.metrics",tagList,threadPoolExecutor,value -> threadPoolExecutor.getCorePoolSize());
}
@Override
public void destroy() throws Exception {
if(Objects.nonNull(scheduledExecutorService)){
scheduledExecutorService.shutdown();
}
}
}
ThreadPoolExecutorRebinder
package com.cxytiandi.threadpool.rebinder;
import com.cxytiandi.threadpool.ThreadPoolManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @ClassName: ThreadPoolExecutorRebinder
* @Description: 重新绑定参数线程池
* @Author: Administrator
* @Date: 2023-12-09 23:53
* @Version:1.0
*/
@Slf4j
public class ThreadPoolExecutorRebinder implements ApplicationListener<EnvironmentChangeEvent>,EnvironmentAware {
private Environment environment;
private static final String split_key = "\\.";
private static final String OPT_CORE_POOL_SIZE = "corePoolSize";
private static final String OPT_MAX_POOL_SIZE = "maxinumPoolSize";
private static final String OPT_KEEP_ALIVE_TIME = "keepAliveTime";
private static final String OPT_SHUTDOWN = "shutdown";
private static final String OPT_SHUTDOWN_FLAG = "1";
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
Set<String> keys = event.getKeys();
List<String> keySet = keys.stream().sorted((o1, o2) -> o2.length() - o1.length()).
filter(line -> line.contains("sc.thread.pool")).
collect(Collectors.toList());
for (String key : keySet) {
String name = key.split(split_key)[3];
String operation = key.split(split_key)[4];
String value = environment.getProperty(key);
Set<ThreadPoolExecutor> poolExecutors = getThreadPoolExecutorByName(name);
applyOperation(poolExecutors,operation,value);
}
}
private void applyOperation(Set<ThreadPoolExecutor> poolExecutors, String operation, String value) {
if(Objects.isNull(value) || poolExecutors.size() == 0){
return;
}
if(OPT_CORE_POOL_SIZE.equalsIgnoreCase(operation)){
// 核心线程数
poolExecutors.forEach(threadPoolExecutor -> {
try {
int corePoolSize = Integer.valueOf(value);
threadPoolExecutor.setCorePoolSize(corePoolSize);
} catch (NumberFormatException e) {
log.error("set corePoolSize err",e);
}
});
}else if(OPT_MAX_POOL_SIZE.equalsIgnoreCase(operation)){
// 最大线程数
poolExecutors.forEach(threadPoolExecutor -> {
try {
Integer maxinumPoolSize = Integer.valueOf(value);
threadPoolExecutor.setMaximumPoolSize(maxinumPoolSize);
} catch (NumberFormatException e) {
log.error("set maxinumPoolSize err",e.getMessage());
}
});
}else if(OPT_KEEP_ALIVE_TIME.equalsIgnoreCase(operation)){
// 存活时间
poolExecutors.forEach(threadPoolExecutor -> {
try {
long time = Long.valueOf(value);
threadPoolExecutor.setKeepAliveTime(time, TimeUnit.MILLISECONDS);
} catch (NumberFormatException e) {
log.error("set keepAliveTime err",e.getMessage());
}
});
}else if(OPT_SHUTDOWN.equalsIgnoreCase(operation)){
poolExecutors.forEach(threadPoolExecutor -> {
try {
if(OPT_SHUTDOWN_FLAG.equalsIgnoreCase(value)){
threadPoolExecutor.shutdown();
}
} catch (Exception e) {
log.error("shutdown err,",e.getMessage());
}
});
}
}
private Set<ThreadPoolExecutor> getThreadPoolExecutorByName(String name) {
return ThreadPoolManager.getThreadPoolExecutor(name);
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}
Named
public interface Named {
public String getName();
}
NamedExecutors
public class NamedExecutors {
/**
* 固定线程池大小
* @param name 线程池名称
* @param nThreads 核心线程数
* @return
*/
public static ExecutorService newFixedThreadPool(String name,int nThreads){
NamedThreadFactory namedThreadFactory = new NamedThreadFactory(name);
return new NamedThreadPoolExecutor(name,nThreads,nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<Runnable>(),namedThreadFactory);
}
/**
* 固定线程池大小
* @param name 线程池名称
* @param nThreads 核心线程数
* @return
*/
public static ExecutorService newFixedThreadPool(String name, int nThreads, ThreadFactory threadFactory){
return new NamedThreadPoolExecutor(name,nThreads,nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<Runnable>(),threadFactory);
}
/**
* 单个线程池
* @return
*/
public static ExecutorService newSingleThreadExecutor(String name){
NamedThreadFactory namedThreadFactory = new NamedThreadFactory(name);
return new NamedThreadPoolExecutor(name,1,1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<Runnable>(),namedThreadFactory);
}
/**
* 单个线程池
* @return
*/
public static ExecutorService newSingleThreadExecutor(String name,ThreadFactory threadFactory){
return new NamedThreadPoolExecutor(name,1,1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<Runnable>(),threadFactory);
}
/**
* 缓存线程池
* @return
*/
public static ExecutorService newCacheThreadPool(String name){
NamedThreadFactory namedThreadFactory = new NamedThreadFactory(name);
return new NamedThreadPoolExecutor(name,0,Integer.MAX_VALUE,0L, TimeUnit.MILLISECONDS,new SynchronousQueue<Runnable>(),namedThreadFactory);
}
/**
* 缓存线程池
* @return
*/
public static ExecutorService newCacheThreadPool(String name,ThreadFactory threadFactory){
return new NamedThreadPoolExecutor(name,0,Integer.MAX_VALUE,0L, TimeUnit.MILLISECONDS,new SynchronousQueue<Runnable>(),threadFactory);
}
/**
* 定时线程池
*/
public static ScheduledThreadPoolExecutor newSingleThreadScheduleThreadExecutor(String name){
NamedThreadFactory namedThreadFactory = new NamedThreadFactory(name);
return new NamedScheduledThreadPoolExecutor(name,1,namedThreadFactory);
}
/**
* 定时线程池
*/
public static ScheduledThreadPoolExecutor newSingleThreadScheduleThreadExecutor(String name,ThreadFactory threadFactory){
return new NamedScheduledThreadPoolExecutor(name,1,threadFactory);
}
/**
* 定时线程池
*/
public static ScheduledExecutorService newScheduleThreadPool(String name, int corePoolSize){
NamedThreadFactory namedThreadFactory = new NamedThreadFactory(name);
return new NamedScheduledThreadPoolExecutor(name,corePoolSize,namedThreadFactory);
}
/**
* 定时线程池
*/
public static ScheduledExecutorService newScheduleThreadPool(String name,int corePoolSize,ThreadFactory threadFactory){
return new NamedScheduledThreadPoolExecutor(name,corePoolSize,threadFactory);
}
NamedScheduledThreadPoolExecutor
public class NamedScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor implements NamedExecutor {
private String name;
public NamedScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize);
}
public NamedScheduledThreadPoolExecutor(String name,int corePoolSize) {
super(corePoolSize);
this.name = name;
NamedThreadFactory namedThreadFactory = new NamedThreadFactory(name);
setThreadFactory(namedThreadFactory);
ThreadPoolManager.addThreadPoolExecutor(this);
}
public NamedScheduledThreadPoolExecutor(String name,int corePoolSize, ThreadFactory threadFactory) {
super(corePoolSize, threadFactory);
this.name = name;
ThreadPoolManager.addThreadPoolExecutor(this);
}
public NamedScheduledThreadPoolExecutor(String name,int corePoolSize, RejectedExecutionHandler handler) {
super(corePoolSize, handler);
this.name = name;
NamedThreadFactory namedThreadFactory = new NamedThreadFactory(name);
setThreadFactory(namedThreadFactory);
ThreadPoolManager.addThreadPoolExecutor(this);
}
public NamedScheduledThreadPoolExecutor(String name,int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
super(corePoolSize, threadFactory, handler);
this.name = name;
ThreadPoolManager.addThreadPoolExecutor(this);
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
}
NamedThreadFactory
public class NamedThreadFactory implements ThreadFactory{
private static final AtomicInteger POOL_SEQ = new AtomicInteger(1);
private static final AtomicInteger mThreadNum = new AtomicInteger(1);
private String mPrefix;
private final boolean mDaemo;
private final ThreadGroup mGroup;
public NamedThreadFactory(String prefix){
this(prefix,false);
}
public NamedThreadFactory(String prefix,boolean daemo){
mPrefix = prefix + "-thread-";
mDaemo = daemo;
SecurityManager sm = System.getSecurityManager();
mGroup = (sm==null) ? Thread.currentThread().getThreadGroup() : sm.getThreadGroup();
}
@Override
public Thread newThread(Runnable runnable) {
String name = mPrefix + mThreadNum .getAndIncrement();
Thread ret = new Thread(mGroup,runnable,name,0);
ret.setDaemon(mDaemo);
return ret;
}
}
NamedThreadPoolExecutor
public class NamedThreadPoolExecutor extends ThreadPoolExecutor implements NamedExecutor {
/**
* 线程池名称
* @return
*/
private String name;
public NamedThreadPoolExecutor(String name, int corePoolSize, int maxPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue){
super(corePoolSize,maxPoolSize,keepAliveTime,unit,workQueue);
this.name = name;
NamedThreadFactory namedThreadFactory = new NamedThreadFactory(name);
setThreadFactory(namedThreadFactory);
ThreadPoolManager.addThreadPoolExecutor(this);
}
public NamedThreadPoolExecutor(String name, int corePoolSize, int maxPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory factory){
super(corePoolSize,maxPoolSize,keepAliveTime,unit,workQueue,factory);
this.name = name;
NamedThreadFactory namedThreadFactory = new NamedThreadFactory(name);
setThreadFactory(namedThreadFactory);
ThreadPoolManager.addThreadPoolExecutor(this);
}
public NamedThreadPoolExecutor(String name, int corePoolSize, int maxPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler){
super(corePoolSize,maxPoolSize,keepAliveTime,unit,workQueue,handler);
this.name = name;
NamedThreadFactory namedThreadFactory = new NamedThreadFactory(name);
setThreadFactory(namedThreadFactory);
ThreadPoolManager.addThreadPoolExecutor(this);
}
public NamedThreadPoolExecutor(String name, int corePoolSize, int maxPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory factory, RejectedExecutionHandler handler){
super(corePoolSize,maxPoolSize,keepAliveTime,unit,workQueue,factory,handler);
this.name = name;
NamedThreadFactory namedThreadFactory = new NamedThreadFactory(name);
setThreadFactory(namedThreadFactory);
ThreadPoolManager.addThreadPoolExecutor(this);
}
@Override
public String getName() {
return this.name;
}
@Override
public void setName(String name) {
this.name = name;
}
SoftReferenceMap
public class SoftReferenceMap<K,V> {
/**
* 将V 对象封装成软引用对象,放置在softReferenceMap里面
*/
private HashMap<K,SoftValue<K,V>> temp;
/**
* 用来存储键入了系统回收队列中的对象,这里对应应该是V
*/
private ReferenceQueue<V> queue;
public SoftReferenceMap(){
super();
this.temp = new HashMap<K,SoftValue<K,V>>();
queue = new ReferenceQueue<V>();
}
public boolean containsKey(Object key){
/**
* 清空正在被系统回收的队列,否则课鞥呢拿到SoftReference中可能已经没有了 key对应的对象
*/
purge();
return temp.containsKey(key);
}
public V get(Object key){
purge();
SoftValue<K,V> softValue= temp.get(key);
if(softValue != null){
return softValue.get();
}
return null;
}
public V put(K key,V value){
SoftValue<K,V> softReference = new SoftValue<>(key,value,queue);
temp.put(key,softReference);
return value;
}
public Set<K> keySet(){
purge();
return temp.keySet();
}
/**
* 从temp中清空 已经键入了回收队列中的对象(V)对应的SoftReference
*/
public void purge(){
// 从queue中拿到当前已经加入回收队列的最后一个V
SoftValue<K,V> softReference = (SoftValue<K,V>)queue.poll();
while (softReference != null){
// 拿到这个V对应的key,把他从temp的map中删除
temp.remove(softReference.key);
// 循环把所有的在回收队列中的值从temp中删除
softReference =(SoftValue<K,V>)queue.poll();
}
}
/**
* 实现一个带键值对的SoftReference,用来保存一个key,供temp快速删除对应的softReference
*/
@SuppressWarnings("hiding")
private class SoftValue<K,V> extends SoftReference<V>{
private K key;
public SoftValue(K k,V v,ReferenceQueue<? super V> q ){
// 把softReference注册到Queue中,系统会在适当时候把V加入到回收队列中
super(v,q);
this.key = k;
}
}
ThreadPoolManager
public class ThreadPoolManager {
/**
* 软引用
*/
private static SoftReferenceMap<ThreadPoolExecutor,ThreadPoolExecutor> softReferenceMap = new SoftReferenceMap<>();
/**
* 添加threadPoolExecutor
* 使用弱引用,防止添加threadPoolExecutor不能回收
*/
public static void addThreadPoolExecutor(ThreadPoolExecutor threadPoolExecutor){
softReferenceMap.putIfAbsent(threadPoolExecutor,threadPoolExecutor);
}
public static Set<ThreadPoolExecutor> getThreadPoolExecutors(){
return softReferenceMap.keySet();
}
/**
* 名字相同的线程池,可能是一个列表
*/
public static Set<ThreadPoolExecutor> getThreadPoolExecutor(String name){
if(Objects.isNull(name)){
return new HashSet<>(1);
}
return softReferenceMap.keySet().stream().filter(threadPoolExecutor -> {
String tName = null;
if(threadPoolExecutor instanceof NamedExecutor){
tName = ((NamedExecutor)threadPoolExecutor).getName();
}else {
tName = threadPoolExecutor.hashCode()+ StringUtils.EMPTY;
}
if(name.equalsIgnoreCase(tName)){
return true;
}
return false;
}).collect(Collectors.toSet());
}
}