美文网首页
ThreadLocal

ThreadLocal

作者: 小飞的学习笔记 | 来源:发表于2019-08-26 21:51 被阅读0次

    1.原始的ThreadLocal如何设计的?

    原始的ThreadLocal是用线程id作为key的一个hashmap.但是这样会有几个问题.
    问题1:当线程变多的时候,这样设计的ThreadLocal会有很多key,最终导致取值效率变低
    问题2:由于ThreadLocal将一直引用变量值,即使线程被销毁了,ThreadLocal中的值有可能仍然没有办法进行GC

    2.基于以上两个问题,我们可以如何优化呢?

    每个Thread都持有一个ThreadLocalMap,这个map使用threadLocal实例作为key,将要存储的值作为值.threadLocal在设置值的时候,直接获取当前的thread并把自身引用和存储的数据put到这个thread中的threadLocalMap中去,取值的时候也直接使用threadLocal实例作为key从当前Thread中的ThreadLocalMap中取到所存储的值.另外,ThreadLocalMap的key使用WeakRefference,这样可以保证threadLocal对象在栈引用销毁后,即使当前线程依然在运行,即使ThreadLocalMap中的Entry依然引用着ThreadLocal实例,这个threadLocal实例依然能够被销毁.并且threadLocal被销毁后,在ThreadLocalMap调用set和getEntry的时候能够销毁threadLocal所对应的值,从而一定程度上避免内存泄漏问题.

    3.新的设计方案如何解决#1的两个问题的?

    1.就算线程变多,对于一个ThreadLocal对象,每个thread中的key的数量都是1,取值效率大大提高
    2.由于现在值是被线程引用,如果线程销毁了,对应所存储的值也将被销毁


    image

    4.新设计的新问题

    1.ThreadLocalMap的key为什么要使用弱引用?
    如果ThreadLocal的栈引用被销毁,若ThreadLocalMap的Entry使用的是强引用,则将导致ThreadLocal对象依然不会被销毁,当前ThreadLocalMap将永远不会销毁这个Entry.但是如果使用弱引用,当栈中的ThreadLocal被销毁,则将导致ThreadLocalMap中的key变为null,当前ThreadLocalMap则能够根据key的引用是否为空来决定是否销毁对应的值,从而避免内存泄漏.
    2.弱引用真的完全解决内存泄漏了吗?
    答案是否定,虽然弱引用机制保证了ThreadLocalRef被销毁后,Entry中的value依然能够被销毁. 但是那个销毁发生在我们调用ThreadLocalMap的set和getEntry的时候,如果我们没有主动调用ThreadLocalMap和set和getEntry,这将仍然导致内存泄漏.

    5.使用方式推荐

    1.ThreadLocal在使用完后如果没有特殊情况记得要主动调用remove以防止内存泄漏
    2.尽量使用private static final ThreadLocal 来定义ThreadLocal对象,使得在同一个线程中一直使用同一个ThreadLocal对象而不用创建多个,但是要注意在线程池中,线程会被复用,如果不调用remove,线程被复用时,前次set的值将仍然存在.

    参考:https://blog.csdn.net/levena/article/details/78027136

    相关文章

      网友评论

          本文标题:ThreadLocal

          本文链接:https://www.haomeiwen.com/subject/uifjectx.html