自定义线程池实现

迈不过友情╰ 2022-12-24 00:35 358阅读 0赞

线程池 - 自定义线程池实现

用线程池来管理线程,减少系统消耗,线程数可控。


目录

线程池 - 自定义线程池实现

一、自定义线程池代码

二、测试


一、自定义线程池代码

自定义使用 ThreadPoolTaskExecutor

  1. package com.yuantiaokj.commonmodule.threadpool;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.scheduling.annotation.EnableAsync;
  6. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  7. import java.util.concurrent.Executor;
  8. import java.util.concurrent.ThreadPoolExecutor;
  9. /**
  10. * ***********************************************************
  11. * Copyright © 2019 Inc.All rights reserved. * *
  12. * **********************************************************
  13. *
  14. * @program: pay_inspector
  15. * @name: TaskExecutePool
  16. * @author: Mr.Cnzz
  17. * @create: 2019-11-28 15:25
  18. * @description: 创建线程池
  19. **/
  20. @Configuration
  21. @EnableAsync
  22. public class TaskExecutePool {
  23. /**
  24. * 1.这种形式的线程池配置是需要在使用的方法上面@Async("taskExecutor"),
  25. * 2.如果在使用的方法上面不加该注解那么spring就会使用默认的线程池
  26. * 3.所以如果加@Async注解但是不指定使用的线程池,又想自己定义线程池那么就可以重写spring默认的线程池
  27. * 4.所以第二个方法就是重写默认线程池
  28. * 注意:完全可以把线程池的参数写到配置文件中
  29. */
  30. @Autowired
  31. private TaskThreadPoolConfig config;
  32. @Bean("taskExecutePoolCnzz")
  33. public Executor taskExecutePoolCnzz() {
  34. ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  35. //核心线程池大小
  36. executor.setCorePoolSize(config.getCorePoolSize());
  37. //最大线程数
  38. executor.setMaxPoolSize(config.getMaxPoolSize());
  39. //队列容量
  40. executor.setQueueCapacity(config.getQueueCapacity());
  41. //活跃时间
  42. executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
  43. //线程名字前缀
  44. executor.setThreadNamePrefix("taskExecutePoolCnzz");
  45. // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
  46. // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
  47. executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
  48. // 等待所有任务结束后再关闭线程池
  49. executor.setWaitForTasksToCompleteOnShutdown(true);
  50. executor.initialize();
  51. return executor;
  52. }
  53. }

配置类

  1. package com.yuantiaokj.commonmodule.threadpool;
  2. import lombok.Data;
  3. import org.springframework.boot.context.properties.ConfigurationProperties;
  4. /**
  5. * ***********************************************************
  6. * Copyright © 2019 Inc.All rights reserved. * *
  7. * **********************************************************
  8. *
  9. * @program: pay_inspector
  10. * @name: TaskThreadPoolConfig
  11. * @author: Mr.Cnzz
  12. * @create: 2019-11-28 15:21
  13. * @description: 线程池配置类
  14. **/
  15. @ConfigurationProperties(prefix = "task.pool")
  16. @Data
  17. @Component
  18. public class TaskThreadPoolConfig {
  19. //核心线程
  20. private int corePoolSize;
  21. //最大线程
  22. private int maxPoolSize;
  23. //空闲时间
  24. private int keepAliveSeconds;
  25. //队列容量
  26. private int queueCapacity;
  27. }

yml 配置线程池参数

  1. #线程池配置参数
  2. task:
  3. pool:
  4. corePoolSize: 20 #设置核心线程数
  5. maxPoolSize: 100 #设置最大线程数
  6. keepAliveSeconds: 60 #设置线程活跃时间(秒)
  7. queueCapacity: 50 #设置队列容量

启动类Application 添加异步注解

  1. //开启线程异步支持
  2. @EnableAsync
  3. // 开启配置属性支持
  4. @EnableConfigurationProperties({TaskThreadPoolConfig.class})

使用,springboot直接使用@Async异步执行


二、测试

  1. @Async
  2. public void printNum(String str) {
  3. log.info("str={}", str);
  4. }
  5. @Resource
  6. AsyncTest asyncTest;
  7. @Test
  8. public void testAsync(){
  9. for (int i = 0; i <20 ; i++) {
  10. asyncTest.printNum(String.valueOf(i));
  11. }
  12. }

这里注意调用方法要在不同的类才会生效,由于容器加载原因,在同一个类时需要容器重新加载下。

1、队列,最大线程数 都较小的情况下,会生成到10个线程,触发饱和策略,也会有主线程执行。

测试配置,实际按环境情况配置,这里为了看到测试效果

  1. #线程池配置参数
  2. task:
  3. pool:
  4. corePoolSize: 2 #设置核心线程数
  5. maxPoolSize: 10 #设置最大线程数
  6. keepAliveSeconds: 10 #设置线程活跃时间(秒)
  7. queueCapacity: 5 #设置队列容量

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpbnB6_size_16_color_FFFFFF_t_70

2、增大队列容量,让在队列等待,只有2个主线程在跑

  1. #线程池配置参数
  2. task:
  3. pool:
  4. corePoolSize: 2 #设置核心线程数
  5. maxPoolSize: 10 #设置最大线程数
  6. keepAliveSeconds: 10 #设置线程活跃时间(秒)
  7. queueCapacity: 20 #设置队列容量

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpbnB6_size_16_color_FFFFFF_t_70 1

3、稍微减少队列,看下当队列满了,及未达到线程总数,未饱和的情况

  1. #线程池配置参数
  2. task:
  3. pool:
  4. corePoolSize: 2 #设置核心线程数
  5. maxPoolSize: 20 #设置最大线程数
  6. keepAliveSeconds: 10 #设置线程活跃时间(秒)
  7. queueCapacity: 15 #设置队列容量

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpbnB6_size_16_color_FFFFFF_t_70 2

具体参数配置及原理可参考 线程池-线程池参数及配置 https://blog.csdn.net/xinpz/article/details/110132365


发表评论

表情:
评论列表 (有 0 条评论,358人围观)

还没有评论,来说两句吧...

相关阅读

    相关 定义线

    如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务; 如果当前线程池中的线程数目>=corePoolSize,则每来一个