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

  

 

  

  

  

 

 

  

 

  

 

posted on   anpeiyong  阅读(243)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示