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
解决子线程无法获取主线程的数据。

浙公网安备 33010602011771号