ThreadLocal

一、作用

  变量实现线程之间隔离

二、原理概述:

ThreadLocal<String> threadLocal = new ThreadLocal<String>(); 

在某个线程内调用threadLocal.set(value)方法时,①先获取当前线程t的ThreadLocalMap map属性,②调用map.set(ThreadLocal, Object)方法,将threadLocal值传入,使用threadLocal值进行位运算&获取数组下标i,map里面有一个Entry<ThreadLocal, Object>[] entry数组,entry数组根据i确定位置得到该下标对应的值e,所以e是一个Entry<ThreadLocal, Object>类型,e.value就是之前保存的值,然后将e.value替换为现在将要保存的Object值。

每次一个线程内新增一个ThreadLocal时,entry数组就会新增一个元素Entry<ThreadLocal, Object> e,这个e放在哪个下标取决于threadLocal引用值和散列算法。同理,在一个线程中去获取threadLocal.get()时,先通过当前线程获取线程的ThreadLocalMap map;然后调用map.getEntry(ThreadLocal threadLocal)方法,先根据threadLocal引用获取数组下标i,Entry<ThreadLocal, Object>[] entry再根据i获取下标对应的值e,e.value()就是要找的数据了。

set方法:

①获取当前线程的ThreadLocalMap map;②map.get(threadLocal),根据threadLocal引用值计算得到的下标i,获取entry数组中下标对应的元素Entry<ThreadLocal, Object> e,将e的value值替换为新的value

get方法:

①获取当前线程的ThreadLocalMap map;②map.get(threadLocal),根据threadLocal引用值计算得到的下标i,获取entry数组中下标对应的元素Entry<ThreadLocal, Object> e,e.value()得到的值就是当前线程保存的值。

三、内存泄漏

  ThreadLocalMap中的Entry数组属性,Entry<ThreadLocal, value> ,其中ThreadLocal是弱引用类型,而value是强引用类型,当发生GC时,ThreadLocal会被回收,而value在线程存活期间一直得不到回收,导致内存泄漏。

  解决方案就是需要在get获取并使用完value之后,调用ThreadLocal的remove方法移除元素,也就是原先数组上对应下标的值置为null,这样就会被回收了。

四、InheritableThreadLocal

解决子线程无法获取主线程的数据。

https://blog.csdn.net/a837199685/article/details/52712547?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-52712547-blog-123835943.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-52712547-blog-123835943.pc_relevant_paycolumn_v3&utm_relevant_index=1

posted @ 2021-08-23 10:47  DustAsh  阅读(66)  评论(0)    收藏  举报