动态化调整线程池

一、概述
     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());
    }


}
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot支持动态创建和管理线程池,可以根据业务需要随时调整线程池大小,以达到最优的线程利用率。 在Spring Boot中,可以通过@Configuration注解定义一个线程池配置类,使用@ConditionalOnProperty注解来判断是否启用线程池,使用@Bean注解来定义线程池对象,并设置相关属性。 以下是一个简单的示例代码: ``` @Configuration @ConditionalOnProperty(name = "myapp.threadpool.enabled", havingValue = "true") public class MyThreadPoolConfig { @Value("${myapp.threadpool.corePoolSize}") private int corePoolSize; @Value("${myapp.threadpool.maxPoolSize}") private int maxPoolSize; @Value("${myapp.threadpool.queueCapacity}") private int queueCapacity; @Value("${myapp.threadpool.keepAliveSeconds}") private int keepAliveSeconds; @Bean public ThreadPoolTaskExecutor myTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.setKeepAliveSeconds(keepAliveSeconds); executor.setThreadNamePrefix("myTaskExecutor-"); executor.initialize(); return executor; } } ``` 在上面的示例中,定义了一个名为myTaskExecutor的线程池对象,通过@Value注解来获取配置文件中的相关属性值,然后设置给线程池对象,并使用initialize()方法初始化线程池。 可以通过在application.yml或application.properties文件中设置相关属性值来配置线程池: ``` myapp: threadpool: enabled: true corePoolSize: 10 maxPoolSize: 100 queueCapacity: 1000 keepAliveSeconds: 60 ``` 在上面的示例中,启用了线程池,设置了核心线程数为10,最大线程数为100,队列容量为1000,线程保活时间为60秒。 使用线程池时,可以通过注入线程池对象来创建和执行线程任务: ``` @Service public class MyService { @Autowired private ThreadPoolTaskExecutor myTaskExecutor; public void doSomethingAsync() { myTaskExecutor.execute(new Runnable() { @Override public void run() { // do something asynchronously } }); } } ``` 在上面的示例中,注入了名为myTaskExecutor的线程池对象,并通过execute()方法来创建和执行一个异步任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值