• 并发容器之ThreadLocal详解


    一、定义

    https://baijiahao.baidu.com/s?id=1653790035315010634&wfr=spider&for=pc

    threadlocal而是一个线程内部的存储类,可以在指定线程内存储数据,数据存储以后,只有指定线程可以得到存储数据

    当使用ThreadLocal维护变量的时候 为每一个使用该变量的线程提供一个独立的变量副本,即每个线程内部都会有一个该变量,这样同时多个线程访问该变量并不会彼此相互影响,因此他们使用的都是自己从内存中拷贝过来的变量的副本, 这样就不存在线程安全问题,也不会影响程序的执行性能。

    但是要注意,虽然ThreadLocal能够解决上面说的问题,但是由于在每个线程中都创建了副本,所以要考虑它对资源的消耗,比如内存的占用会比不使用ThreadLocal要大。

    举例:

    ThreadLocal<String> localName = new ThreadLocal();
    localName.set("小狼");
    String name = localName.get();

    在线程1中初始化了一个ThreadLocal对象localName,并通过set方法,保存了一个值小狼,同时在线程1中通过localName.get()可以拿到之前设置的值,但是如果在线程2中,拿到的将是一个null。

    在ThreadLoalMap中,也是初始化一个大小16的Entry数组,Entry对象用来保存每一个key-value键值对,只不过这里的key永远都是ThreadLocal对象,通过ThreadLocal对象的set方法,结果把ThreadLocal对象自己当做key,放进了ThreadLoalMap中。

    二、ThreadLocal的工作原理

    1.每个Thread实例内部都有一个ThreadLocalMap,ThreadLocalMap是一种Map,它的key是ThreadLocal,value是Object。

    2. 存数据 是往当前线程的ThreadLocalMap中存入数据,其key是当前ThreadLocal对象,value是set方法中传入的值。

    3.使用数据时,以当前ThreadLocal为key,从当前线程的ThreadLocalMap中取出数据。

    三、ThreadLocal内存泄漏分析与解决方案

    ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用,而 value 是强引用。所以,如果 ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候,key 会被清理掉,而 value 不会被清理掉。这样一来,ThreadLocalMap 中就会出现key为null的Entry。假如我们不做任何措施的话,value 永远无法被GC 回收,这个时候就可能会产生内存泄露。ThreadLocalMap实现中已经考虑了这种情况,在调用 set()、get()、remove() 方法的时候,会清理掉 key 为 null 的记录。使用完 ThreadLocal方法后 最好手动调用remove()方法

    造成内存泄漏的原因:

    1.key为弱引用,gc之后key为null,导致value无法被获取到
    2.ThreadLocalMap的生命周期与Thread相同,导致内存泄漏一直存在

    解决方案: 

    每次使用完ThreadLocal,都调用它的remove()方法,清除数据。

    通过下图进行分析:

    ThreadLocal本身并不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value

     现在,我们假设ThreadLocal完成了自己的使命,与ThreadLocalRef断开了引用关系。此时内存图变成了这样。

     系统GC发生时,由于Heap中的ThreadLocal只有来自key的弱引用,因此ThreadLocal内存会被回收到。

     到这里,value被留在了Heap中,而我们没办法通过引用访问它。value这块内存将会持续到线程结束。造成内存泄漏。

  • 相关阅读:
    转载 | CSS文本溢出显示省略号
    转载 | CSS书写顺序
    转载 | CSS布局大全
    threejs sprite 制作标签
    typeScript 中的类
    Es5中的类
    typeScript中的函数
    websocket在vue项目中的使用
    typeScript中的变量数据类型
    echarts 中的1/4圆环行图的使用
  • 原文地址:https://www.cnblogs.com/jingpeng77/p/12881743.html
Copyright © 2020-2023  润新知