threadlocal原理及常用应用场景一张图看懂ThreadLocal原理ThreadLocal的原理和使用场景




threadlocal原理及常用应用场景一张图看懂ThreadLocal原理ThreadLocal的原理和使用场景

2022-07-21 2:26:17 网络知识 官方管理员

threadlocal原理及常用应用场景(一张图看懂ThreadLocal原理)(1)

图解:该图基于Android中的ThreadLocal在Looper中的应用,其能够实现一个线程只有一个Looper的私有实例,左边是通过代码分析得到的类关系图,我们可以看到可以通过线程得到一个Looper,首先通过Thread里的成员变量得到ThreadLocalMap,然后通过Looper中的静态变量能够得到ThreadLocals如下代码,

threadlocal原理及常用应用场景(一张图看懂ThreadLocal原理)(2)

然后通过ThreadLocals实例得到Map中的Entry然后在通过该实例得到Looper的实例,如下

threadlocal原理及常用应用场景(一张图看懂ThreadLocal原理)(3)

另外,右图是在该应用中的各种类的引用关系链,通过它我们可以分析到为什么Entry引用key是用的弱引用。我们在android中有可能会用到Looper.quit简单讲就将Looper实例置为null让垃圾回收器回收。此时分析右图,可知,当Looper为null时,ThreadLocal的实例也就没有太大的用处了,也需要进行回收,但是如果Entry引用key是用的强应用,ThreadLocal的实例就不能回收,如果是弱引用的话,就可以在垃圾回收GC的时候强行回收掉。但仅仅是这样还不行,在某些情况下还是会出现问题,这就需要具体情况具体分析,下面看一个来自文章https://mp.weixin.qq.com/s/vURwBPgVuv4yGT1PeEHxZQ的例子:

threadlocal原理及常用应用场景(一张图看懂ThreadLocal原理)(4)

分析该例子的引用链如下

threadlocal原理及常用应用场景(一张图看懂ThreadLocal原理)(5)

TestClass的实例置null是想释放int的空间,但是不好意思,我还是能够有引用链到达int,通过Thread->Entry->TestClass->int,可能有人问TestClass实例不是置null了么,TestClass的实例t,只是线程中Thread中的一个引用置null了,也就是说thread->TestClass这条线不可达,但是Thread->Entry->TestClass->int是可达的,所以会内存泄露,与是内存溢出。解决方案是remove函数,即溢出Entry对TestClass的引用,源码如下:

privatevoidremove(ThreadLocal<?>key){

Entry[]tab=table;

intlen=tab.length;

inti=key.threadLocalHashCode&(len-1);

for(Entrye=tab[i];

e!=null;

e=tab[i=nextIndex(i,len)]){

if(e.get()==key){

e.clear();

expungeStaleEntry(i);

return;

}

}

}

publicvoidclear(){

this.referent=null;

}

发表评论:

最近发表
网站分类
标签列表