美文网首页线程池
线程池系列(6)如何统一管理旧项目中的线程池

线程池系列(6)如何统一管理旧项目中的线程池

作者: 小胖学编程 | 来源:发表于2022-03-11 21:03 被阅读0次

问题:在一个项目中,每一台机器活跃线程数有时候会有1000-2000个。当机器中存在大量无用的活跃线程时,便会影响性能,那么如何处理这种情况???

1. 问题

本文不讲述线程池是如何被统一管理的。重点描述:在旧已有项目中如何找到并管理已经存在的线程池。

项目中线程池的用法五花八门:

  1. 在类属性中声明JDK线程池;
  2. 使用@Autowired自动注入Spring的线程池;
  3. 在一个公共工具类中声明多个JDK线程池,类的方法中直接使用线程池;

每个人编码风格不同,线程池的声明方式不同;每个人的对线程池的理解不同,所以核心参数的配置也就不同。导致了线程池的不可管理。

2. 解决方案

原理:借助于Spring的Bean的初始化流程+反射机制去解决这个问题。

项目在启动过程中,会将初始化Bean对象,此时会经过BeanPostProcessor方法对bean进行代理增强处理(例如依赖BeanPostProcessor实现事务,依赖注入等)。

相关文章:

Spring进阶篇(5)- BeanPostProcessor(Bean的后置处理器)
Spring进阶篇(10)-BeanPostProcessor的注册时机

Spring进阶篇(9)- MethodValidationPostProcessor 后置处理器的运用

那么能否在初始化Bean时,通过反射技术来实现属性的增强?

2.1 引入相关依赖

引入反射相关依赖:

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.10</version>
</dependency>

引入TTL依赖:目的是它会重写线程池,来实现ThreadLocal跨线程参数传递(目的为了测试)

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>transmittable-thread-local</artifactId>
    <version>2.11.5</version>
    <scope>compile</scope>
</dependency>

JAVA进阶篇(8)—TransmittableThreadLocal—父子线程间线程本地变量

从TransmittableThreadLocal使用前调研(源码分析)

2.2 代码实现

实现代码:本段代码是一个思路,细节还需单独处理。

@Slf4j
@Component
public class ExtendExecutorsBeanPostProcessor implements BeanPostProcessor, PriorityOrdered {


    private int order = Ordered.LOWEST_PRECEDENCE - 1;

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        //只处理本项目的bean
        if(bean.getClass().getName().contains("com.tellme")) {
            //反射得到的是ExecutorService、ThreadPoolExecutor的属性。
            Set<Field> allFields =
                    ReflectionUtils.getFields(bean.getClass(),
                            i -> i != null && (i.getType().equals(ExecutorService.class) || i.getType()
                                    .equals(ThreadPoolExecutor.class)));

            allFields.stream().forEach(f -> {
                f.setAccessible(true);
                try {
                    //获取类中属性
                    ThreadPoolExecutor executorService = (ThreadPoolExecutor) f.get(bean);
                    //对原有线程池的装饰,使用到TTL线程池(此处不能是ThreadPoolExecutor类,否则会转换不过去)
                    ExecutorService ttlExecutorService =
                            TtlExecutors.getTtlExecutorService(executorService);
                    //替换
                    f.set(bean, ttlExecutorService);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            });
        }
        return bean;
    }

    @Override
    public int getOrder() {
        return this.order;
    }
}

2.3 代码测试

@Slf4j
@RestController
public class ThreadLocalController {

    private ExecutorService executorService = new ThreadPoolExecutor(1, 2,
            60L, TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>());

    public static TransmittableThreadLocal<User> local = new TransmittableThreadLocal<>();
    public static ThreadLocal<User> local2 = new ThreadLocal<>();


    @RequestMapping("/local/t1")
    public void t1(@RequestBody User user) {
        //第一次使用线程池时前,创建多个ThreadLocal的值。
        local.set(user);
        local2.set(user);
        System.out.println(executorService.getClass());
        executorService.execute(() -> {
            log.info("【/local/t1的add操作】子线程打印数据1:{}", local.get());
            log.info("【/local/t1的add操作】子线程打印数据2:{}", local2.get());
        });


    }


    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    private static class User{
        private String id;

        private String name;
    }

}

相关文章

  • 线程池系列(6)如何统一管理旧项目中的线程池

    问题:在一个项目中,每一台机器活跃线程数有时候会有1000-2000个。当机器中存在大量无用的活跃线程时,便会影响...

  • java----线程池

    什么是线程池 为什么要使用线程池 线程池的处理逻辑 如何使用线程池 如何合理配置线程池的大小 结语 什么是线程池 ...

  • 线程池的原理

    线程数量和队列的关系流程的示意图线程池的优势小刘老实讲源码 线程池的优势 线程池是 Java 中对线程进行统一管理...

  • Android 线程池原理

    线程池核心类 : ThreadPoolExecutor:提供了一系列参数来配置线程池 线程池优点: 1.重用线程池...

  • Java中的线程池的集中管理和监控

    背景 需要将项目中的线程池统一管理,并且提供统一的监控。不至于等到程序崩溃的时候才发现。 思路 1、所有的线程池统...

  • 线程池

    JDK线程池 为什么要用线程池 线程池为什么这么设计 线程池原理 核心线程是否能被回收 如何回收空闲线程 Tomc...

  • 线程池

    1、为什么要使用线程池2、线程池的工作原理3、线程池参数4、阻塞队列5、饱和策略6、向线程池提交任务7、线程池的状...

  • Android线程池

    一、为什么使用线程池1.线程池吃好处(1).对多个线程进行统一管理,避免资源竞争中出现问题(2).(重点)对线程进...

  • 分析jdk-1.8-ForkJoinPool实现原理(上)

    Java并发编程源码分析系列: 分析Java线程池的创建 分析Java线程池执行原理 分析Java线程池Calla...

  • 分析jdk-1.8-ForkJoinPool实现原理(下)

    Java并发编程源码分析系列: 分析Java线程池的创建 分析Java线程池执行原理 分析Java线程池Calla...

网友评论

    本文标题:线程池系列(6)如何统一管理旧项目中的线程池

    本文链接:https://www.haomeiwen.com/subject/rlocdrtx.html