前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何统一管理旧项目中的线程池

如何统一管理旧项目中的线程池

作者头像
用户7741497
发布2022-03-24 12:02:51
3280
发布2022-03-24 12:02:51
举报
文章被收录于专栏:hml_知识记录

1. 问题

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

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

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

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

2. 解决方案

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

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

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

2.1 引入相关依赖

引入反射相关依赖:

代码语言:javascript
复制
<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.10</version>
</dependency>

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

代码语言:javascript
复制
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>transmittable-thread-local</artifactId>
    <version>2.11.5</version>
    <scope>compile</scope>
</dependency>

2.2 代码实现

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

代码语言:javascript
复制
@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 代码测试

代码语言:javascript
复制
@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;
    }

}

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 问题
  • 2. 解决方案
    • 2.1 引入相关依赖
      • 2.2 代码实现
        • 2.3 代码测试
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档