其他分享
首页 > 其他分享> > 谈谈ThreadLocal的应用场景和注意事项?

谈谈ThreadLocal的应用场景和注意事项?

作者:互联网

ThreadLocal和Sychronized都用于解决多线程间的并发访问,但它们实现的本质方法不同:sychronized利用锁使同一个代码块或变量在某时刻只能被一个线程访问,而ThreadLocal则为所有线程都提供一个变量副本,这样在某一时刻不同线程访问到的是本质上不同的变量。 ThreadLocal的底层是一个TMap(ThreadLocalMap),向ThreadLocal中存东西相当于向TMap中存东西. 存东西:(当前线程id,TMap)->得到TMap->TMap(当先线程id,保存的值),从当前线程id获取TMap,得到TMap之后, 往TMap里面存值 ThreadLocalMap tmap=getMap(Thread.currentThread());//(当前线程id,TMap) tmap.set(this,value);//(当先线程id,保存的值)   取东西:(当前线程id,TMap)->得到TMap->TMap(当先线程id,保存的值),从当前线程id获取TMap,得到TMap之后,从TMap里面取值 ThreadLocalMap tmap=getMap(Thread.currentThread());//(当前线程id,TMap) ThreadLocalMap.Entry entry=tmap.getEntry(this);//(当先线程id,保存的值) Object ob=entry.value;//(当先线程id,保存的值)  
  1. 数据库连接

 

 

 

测试:

 

主线程中定义static型的ThreadLocal,上面代码中每个线程第一次获取connection时,都会往ThreadLocal中存一份自己的connection,往后直接用就可以了   (1)内存泄漏:TMap(当先线程id,保存的值)中的key为ThreadLocal弱引用,在系统GC的时候,若没有强引用去引用这个弱引用,这个弱引用就会被回收掉,则key就会变为null,这样TMap中就会出现key为null的Entry,也就不能访问到key为null的Entry对应的value,此时若线程迟迟不结束(使用static型ThreadLocal时,生命周期不会随线程结束而结束),则key为null的Entry对应的value永远无法访问,造成内存泄漏。 解决方法:在不同线程的TMap中清除key=null的value (2)脏数据:线程池会复用Thread对象,故而Thread对象中的static静态属性ThreadLocal也会被复用,所以需要显示调用remove()清理掉静态属性ThreadLocal的信息,否则若下一个复用的线程若不调用set()设置该线程初始值,而直接调用get()就会获取到它前一个线程设置的值

 

 

标签:TMap,场景,value,ThreadLocal,线程,key,注意事项,id
来源: https://www.cnblogs.com/afei1759/p/14618176.html