美文网首页
ThredLocal杂谈

ThredLocal杂谈

作者: MIRROR1217 | 来源:发表于2021-06-26 23:32 被阅读0次

最近看到一篇关于ThreadLocal的文章,比较有意思,也有些感悟,正好写下来

1.什么是ThreadLocal

  我第一次看到这个名字,就猜和线程Thread有关,翻译为本地线程。后来看了下,发现它真实的作用是线程变量副本,或者提供线程变量隔离的能力。

2.ThreadLocal的作用及机制

  顾名思义,ThreadLocal有一种能力,对于同一个对象,不同线程下可以独立的变化而不影响其他线程的对象。
  那么它是怎么做到的呢?很简单,每个线程有个Map存储对象信息。比如A线程有个AMap,B线程有个BMap,当线程要存储对象CObject时,AMap通过map.put(key,CObject)方法将对象存储起来,同理BMap也将对象存储起来。这样,两个对象分别将对象存储起来了,就达到隔离的目的了。
  这个时候有个新问题产生了,线程中Map的key是谁?很明显,这个key基本只有两种可能,一个是本地Thread,另一个是ThreadLocal。那么假设是Thread,那么有另外一个变量怎么办,这样会把原来的变量覆盖掉,所以只能把ThreadLocal当做key。当需要保存多个变量时,新建多个ThreadLocal就可以了。那么这个问题可以优化吗?这个后面再说

3.Thread中Map的作用和结构

  Thread中的Map全名叫ThreadLocalMap,是ThreadLocal内部类。ThreadlocalMap只有一个作用,那就是保存线程变量。
  它内部结构,是数组实现的,但是它和HashMap不一样,它采用的是开放定址法。就是当它的地址发生冲突后,会将其往后移一位。如果后面还有冲突,继续往后移动。如果长度到底,则进行扩容。

4.ThreadLocal的内存泄漏问题

  ThreadLocalMap的key是WeakReference类型(Java引用类型),这样可以尽最大努力避免内存泄漏。如图所示:

IMG_20210626_230117.jpg
  从图中可以看到,首先ThreadLocal是个强引用,而且又被ThreaLocalMap的key引用,这个是WeakRefrence引用。只要ThreadLocal被强引用着,GC不会回收ThreadLocal对象。
  那这样设计WeakRefrence还有什么作用呢?根据JVM根搜索算法,在线程中,一直存在Thread -> ThreadLocalMap -> Entry这样一条引用链路。如果key不设计成WeakRefrence类型,就一直不会被GC回收,key就一直不会是null,那么Entry元素就一直不会被清理。所以ThreadLocal的设计者认为只要ThreadLocal所在的作用域结束了工作被清理了,GC回收的时候就会把key引用回收,key置为null,ThreadLocal会尽力保证Entry清理掉来最大可能避免内存泄漏。
  那么如何解决ThreadLocal内存泄漏问题?可以手动调用remove()方法。

5.ThreadLocal多个对象问题?

  前面说过,如果要存储多个对象,那么我们就要新建多个ThreaLocal对象,那么有什么解决办法呢?有的,再封装一下,只要把value设置成Map就可以了。

相关文章

网友评论

      本文标题:ThredLocal杂谈

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