1)概述
多个线程对共享变量进行访问时容易出现线程安全问题,但如果设置成局部变量又不能在同线程方法间共享,因此JDK包提供 ThreadLocal 用来保证线程共享变量访问的安全问题。如果在全局内存中创建了一个ThreadLocal 变量,那么每个线程访问这个变量时都会在线程本地空间中创建一个该变量的副本,接下来在线程中对于该变量的操作都是针对线程本地内存的操作。
2)操作方法
① set() 方法可用于添加内容至本地threadLocal变量中;
② get() 方法可获取其中的内容;
③ emove() 方法可清除其中的内容【后面不再使用时应该及时清除掉,否则会造成溢出】。
3)原理
当线程第一次调用set/get方法时会在底层创建一个ThreadLocalMap,这是一个定制的HashMap,实际上set设置的内容并不是存在ThreadLocal实例中,而是存在当前线程对象的threadLocals属性中,这个属性就是ThreadLocalMap类型。
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
可以看到key是ThreadLocal类型,value就是对应的值了。这里还需要注意key是弱引用类型,也就是说它会在垃圾回收的时候被清除,但是value是Object类型,是强引用类型,并不会被清除掉,就会造成一些key为null的Entry无法被清理掉,积攒多了就有内存溢出的危险了。
4)释放value内存
① get时会清理掉该位置上key为null的Entry;
② set时会进行启发式扫描,清理该位置附近的key为null的Entry;
③ 不使用的时候手动调用remove方法释放。