• ThreadLocal


    ThreadLocal

    在多线程情况下,在线程类中使用ThreadLocal可以为每个线程配置私有的对象

        ThreadLocal<Object> threadLocal = new ThreadLocal<>();
    
    • 1

    比如可以这样使用,用 ThreadLocal 保存用户信息,里面的值可以存放用户信息,不是公用属性不会存在多线程并发问题:

    private static ThreadLocal<LoginUserInfo> USER_INFO_CACHE = new ThreadLocal();
    
    • 1

    用法

    他们使用 get()和 set() 方法来获取默认值或将其值更改为当前线程所存的副本的值,从而避免了线程安全问题

    底层结构

    这个类中只有一个ThreadLocal对象,但是每一个线程中都有不同的ThreadLocalMap

    最终的变量是放在了当前线程的ThreadLocalMap中,并将ThreadLocal这个对象的弱引用作为键

    	//ThreadLocal的set方法可以说明一切
        public void set(T value) {
        	//这个t代表当前线程
            Thread t = Thread.currentThread();
            //ThreadLocalMap是ThreadLocal的内部类,这让每个线程都有一个map
            ThreadLocalMap map = getMap(t);
            //map没有得到,创建一个当前线程的map
            //有map则向map中存值
            if (map != null) {
                map.set(this, value);
            } else {
                createMap(t, value);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    ThreadLocal的hash

    ThreadLocalMap类似hashmap,但是所使用的hash函数、碰撞处理等方法大不相同

    碰撞处理使用动态寻址法

    ThreadLocalMap中存储的是entry,这个是ThreadLocalMap的内部类,它是一个ThreadLocal类型的弱引用,在map中充当键的位置

    在ThreadLocalMap.set()方法的最后,如果执行完启发式清理工作后,未清理到任何数据,且当前散列数组中Entry的数量已经达到了列表的扩容阈值(len*2/3),就开始执行rehash()逻辑,也就是扩容处理

    内存泄漏

    让一个虚引用当值主要是为了防止内存泄漏,当ThreadLocal需要被回收的时候,如果在map中的键是强引用,那么这个对象是无法被回收掉的

            static class Entry extends WeakReference<ThreadLocal<?>> {
                /** The value associated with this ThreadLocal. */
                Object value;
    
                Entry(ThreadLocal<?> k, Object v) {
                    super(k);
                    value = v;
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    ThreadLocal需要我们解决的的内存泄漏问题是下面这种

    因为ThreadLocalMap的键为弱引用,值为强引用,每次GC后,键的指向都为null(因为ThreadLoacl被回收掉了,但是这个弱引用指针并没有被回收),值的指向对象依然没有被回收,产生了OOM问题

    解决办法是在使用完毕后调用remove方法手动清除

    过期删除处理

    当Map中的键指向null的时候代表这个数据过期了,需要被回收掉,ThreadLocal提供了俩种过期删除策略

    1,探测式清理操作
    2,启发式清理

  • 相关阅读:
    elementplus、vxe、surely 三种表格组件的封装
    为什么 vm._data.date1 vm.date1 都可以访问,并且访问 同一个变量
    MySQL需要了解的常用命令
    java-php-python-红河旅游信息服务系统计算机毕业设计
    地形有通挂支隘险远六种情况
    Mybatis缓存机制
    数学逻辑下的动态区间计算公式代码
    鸿鹄工程项目管理系统em Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统
    msm8953 LCD dtsi文件的配置选项含义说明(详解)
    如何使用 Tokenview NFT API进行 NFT 钱包的开发?
  • 原文地址:https://blog.csdn.net/sekever/article/details/126752016