• 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,启发式清理

  • 相关阅读:
    使用adb shell 命令接收串口发送过来的16进制数据 或者 发送16进制数据
    网络安全1
    web开发初级工程师学习笔记
    程序性能分析
    Ubuntu20.04 (VMware 虚拟机) fdisk -l 权限不够的解决办法
    【AI】Deepstream入门(2)Ubuntu20.04安装Deepstream
    计算机硬件和软件之间的区别
    MySQL基础(DDL、DML、DQL)
    LeetCode每日一题——652. 寻找重复的子树
    Android C++系列:Linux网络(三)协议格式
  • 原文地址:https://blog.csdn.net/sekever/article/details/126752016