Java - ThreadLocal和线程池

素颜马尾好姑娘i 2021-12-01 13:12 373阅读 0赞

简单说明

ThreadLocal的目的是把数据存储在线程对象中。数据随着线程的销毁而销毁。InheriableThreadLocal不同于ThreadLocal的地方是,后者只能是同一个线程对象,而前者可以不是同一个线程对象,但前提是这个线程对象的父线程是同一个线程对象,例如,T1存储了D1,又开辟了一个T1-1线程,那么在T1-1线程中可以拿到T1存储的数据。

线程池引发的问题

如果采用了线程池,那么一个线程会被多次使用,如果第一次使用时存储了数据,那么第二次依然可以拿到,因为线程还是同一个。这种场景很常见,我们常用的Tomcat默认就使用了线程池,且默认产生了10个线程备用。这种情况下,就需要清理掉ThreadLocal产生的线程数据。

AOP清理

如果ThreadLocal我们只允许在Service层使用,那么我们可以通过AOP切面在service方法执行完毕后,通过反射或指定变量名称来移除TheadLocal。调用ThreadLocal对象的remove方法即可。

清理器清理

我们可以编写清理器,如下:

  1. package com.codegen.core.utils;
  2. import java.lang.reflect.Field;
  3. import java.lang.reflect.Method;
  4. /** * ThreadLocal清理器 * @author Caesar Liu * @date 2019-07-20 16:27 */
  5. public class ThreadLocalClearer {
  6. /** * 清理对象ThreadLocal对象 * @author Caesar Liu * @date 2019-07-20 16:28 */
  7. public static void clear(Object obj) {
  8. Field[] fields = obj.getClass().getDeclaredFields();
  9. try {
  10. for (Field field: fields) {
  11. if (field.getType().equals(ThreadLocal.class)) {
  12. String getMethod = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
  13. field.setAccessible(true);
  14. Method method =obj.getClass().getMethod(getMethod);
  15. Object value = method.invoke(obj);
  16. if (value == null)
  17. continue;
  18. ThreadLocal threadLocal = (ThreadLocal) value;
  19. threadLocal.remove();
  20. field.setAccessible(false);
  21. }
  22. }
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. }

在使用了ThreadLocal的类中,为ThreadLocal属性增加get方法。在方法调用结束后调用ThreadLocalClearer.clear(this)即可。

发表评论

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

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

相关阅读

    相关 线线

    现在是多核的时代,面向多核编程很重要,因些基于java的并发和多线程编程很重要。 首先要提到的就是线程池,与每次需要创建线程相比,线程池可以降低创建线程的开销,这是因为线程池在

    相关 线线

    软件大师又要给弟子开小灶了,这次是线程和线程池。 软件大师正在闭目修炼, 最小的一名弟子慢慢走了进来。 大师,最近我在学习线程,有很多迷惑的地方。 说来听听,让

    相关 Java线线

    创建线程的方式:继承Thread   、 实现Runnable接口  、实现Callable接口(可以通过Future获取返回结果) 介绍一下通过Callable实现多线程: