ThreadPoolExecutor---动态线程池+监控
背景
实现
nacos + springboot
nacos
https://nacos.io/zh-cn/docs/quick-start.html
下载解压
unzip nacos-server-$version.zip 或者 tar -xvf nacos-server-$version.tar.gz cd nacos/bin
启动
sh startup.sh -m standalone
控制台
http://127.0.0.1:8848
工程结构
由2个模块组成,dtp单独作为动态线程池模块,test为测试模块(依赖dtp)
父pom
dtp模块
pom
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version> 2.2 . 2 .RELEASE</version> </dependency> <!-- nacos consumer--> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>nacos-config-spring-boot-starter</artifactId> <version> 0.2 . 7 </version> </dependency> </dependencies> |
自定义线程池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * @author apy * @description * @date 2023/8/11 11:21 */ public class DtpExecutor extends ThreadPoolExecutor { public DtpExecutor( int corePoolSize, int maximumPoolSize) { super (corePoolSize, maximumPoolSize, 100 , TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>( 100 )); } } |
nacos配置
1 2 3 4 5 6 7 8 | dtp: executors: - name: t1 core-pool-size: 15 max-pool-size: 20 - name: t2 core-pool-size: 12 max-pool-size: 20 |
nacos配置对应的多线程池class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.List; @ConfigurationProperties (prefix = "dtp" ) // 与nacos的配置文件dtp.yml进行绑定 public class DtpProperties { private List<DtpExecutorProperties> executors; public static class DtpExecutorProperties{ private String name; private Integer corePoolSize = 10 ; private Integer maxPoolSize = 10 ; public String getName() { return name; } public void setName(String name) { this .name = name; } public Integer getCorePoolSize() { return corePoolSize; } public void setCorePoolSize(Integer corePoolSize) { this .corePoolSize = corePoolSize; } public Integer getMaxPoolSize() { return maxPoolSize; } public void setMaxPoolSize(Integer maxPoolSize) { this .maxPoolSize = maxPoolSize; } } public List<DtpExecutorProperties> getExecutors() { return executors; } public void setExecutors(List<DtpExecutorProperties> executors) { this .executors = executors; } } import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.context.EnvironmentAware; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.ResolvableType; import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotationMetadata; /** * @author apy * @description * @date 2023/8/11 14:50 */ public class DtpImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware { private Environment environment; public void setEnvironment(Environment environment) { this .environment = environment; } public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) { // 从当前spring容器environment中读取DtpProperties DtpProperties dtpProperties = new DtpProperties(); Binder binder = Binder.get(environment); ResolvableType resolvableType = ResolvableType.forClass(DtpProperties. class ); Bindable<Object> target = Bindable.of(resolvableType).withExistingValue(dtpProperties); binder.bind( "dtp" , target); // 遍历DtpProperties,注册BeanDefinition for (DtpProperties.DtpExecutorProperties executorProperties : dtpProperties.getExecutors()){ AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); beanDefinition.setBeanClass(DtpExecutor. class ); beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(executorProperties.getCorePoolSize()); beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(executorProperties.getMaxPoolSize()); registry.registerBeanDefinition(executorProperties.getName(), beanDefinition); } } } |
线程池工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class DtpUtil { public static Map<String, DtpExecutor> map = new HashMap<String, DtpExecutor>(); public static void setMap(String name, DtpExecutor dtpExecutor) { map.put(name, dtpExecutor); } public static DtpExecutor get(String name){ return map.get(name); } } public class DtpBeanPostProcessor implements BeanPostProcessor { public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof DtpExecutor){ DtpUtil.setMap(beanName, (DtpExecutor) bean); } return bean; } } |
nacos监听器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | import com.alibaba.nacos.api.annotation.NacosInjected; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.config.listener.Listener; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.source.ConfigurationPropertySource; import org.springframework.boot.context.properties.source.MapConfigurationPropertySource; import org.springframework.core.ResolvableType; import org.springframework.core.io.ByteArrayResource; import java.util.Properties; import java.util.concurrent.Executor; import java.util.concurrent.Executors; /** * @author apy * @description * @date 2023/8/11 12:01 */ public class NacosDtpListener implements Listener, InitializingBean { @NacosInjected private ConfigService configService; public Executor getExecutor() { return Executors.newSingleThreadExecutor(); } /** * 当nacos指定配置文件发生变化时,调用this.getExecutor()获得线程池,触发receiveConfigInfo执行 * @param config */ public void receiveConfigInfo(String config) { // 读取nacos的dtp.yml YamlPropertiesFactoryBean bean = new YamlPropertiesFactoryBean(); bean.setResources( new ByteArrayResource(config.getBytes())); Properties properties = bean.getObject(); // 将nacos配置转换为DtpProperties DtpProperties dtpProperties = new DtpProperties(); ConfigurationPropertySource sources = new MapConfigurationPropertySource(properties); Binder binder = new Binder(sources); ResolvableType resolvableType = ResolvableType.forClass(DtpProperties. class ); Bindable<Object> target = Bindable.of(resolvableType).withExistingValue(dtpProperties); binder.bind( "dtp" , target); // 遍历DtpProperties获取对应的DtpExecutor,更新参数 for (DtpProperties.DtpExecutorProperties executorProperties : dtpProperties.getExecutors()){ DtpExecutor dtpExecutor = DtpUtil.get(executorProperties.getName()); dtpExecutor.setCorePoolSize(executorProperties.getCorePoolSize()); dtpExecutor.setMaximumPoolSize(executorProperties.getMaxPoolSize()); } } /** * spring容器启动时,将NacosDtpListener 与 nacos配置文件dtp.yml进行绑定 * @throws Exception */ public void afterPropertiesSet() throws Exception { configService.addListener( "dtp.yml" , "DEFAULT_GROUP" , this ); } } |
动态线程池监视器(由一个定时任务线程,定时去监控线程池变化)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import org.springframework.beans.factory.InitializingBean; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * @author apy * @description * @date 2023/8/11 15:40 */ public class DtpMonitor implements InitializingBean { private ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor( 1 ); public void afterPropertiesSet() throws Exception { executorService.scheduleAtFixedRate(() -> { for (Map.Entry<String, DtpExecutor> dtpExecutorEntry : DtpUtil.map.entrySet()) { String executorName = dtpExecutorEntry.getKey(); DtpExecutor dtpExecutor = dtpExecutorEntry.getValue(); int activeCount = dtpExecutor.getActiveCount(); if (activeCount > 2 ){ System.out.println(String.format( "%s线程池活跃线程数是:%s" , executorName, activeCount)); } } }, 5 , 5 , TimeUnit.SECONDS); } } |
dtp配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; /** * @author apy * @description * @date 2023/8/11 11:42 */ @Configuration @EnableConfigurationProperties (value = DtpProperties. class ) @Import (value = {DtpImportBeanDefinitionRegister. class , DtpBeanPostProcessor. class }) public class DtpConfig { @Bean public NacosDtpListener nacosDtpListener(){ return new NacosDtpListener(); } @Bean public DtpMonitor dtpMonitor(){ return new DtpMonitor(); } } |
test模块
pom
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version> 2.2 . 2 .RELEASE</version> </dependency> <!-- nacos consumer--> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>nacos-config-spring-boot-starter</artifactId> <version> 0.2 . 7 </version> </dependency> <dependency> <groupId>org.example</groupId> <artifactId>dtp</artifactId> <version> 1.0 -SNAPSHOT</version> </dependency> </dependencies> |
controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @RestController public class Controller { @GetMapping (value = "/test1" ) public Integer test1(){ DtpExecutor t1 = DtpUtil.get( "t1" ); t1.execute(() -> doTask()); return t1.getCorePoolSize(); } @GetMapping (value = "/test2" ) public Integer test2(){ DtpExecutor t2 = DtpUtil.get( "t2" ); t2.execute(() -> doTask()); return t2.getCorePoolSize(); } private void doTask(){ try { Thread.sleep( 1000 ); } catch (InterruptedException e) { e.printStackTrace(); } } } |
starter
1 2 3 4 5 6 | @SpringBootApplication public class Starter { public static void main(String[] args) { SpringApplication.run(Starter. class , args); } } |
application.yml
1 2 3 4 5 6 7 8 | nacos: config: service-addr: 127.0 . 0.1 : 8848 data-id: dtp.yml type: yaml auto-refresh: true bootstrap: enable: true |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)