目录
三、ThreadLocalMap将ThreadLocal实例作为key的好处
三、ThreadLocalMap作为Thread的成员变量所带来的问题
一、前言
Java底层为了更好的维护多个线程之间的数据安全以及数据的轻便就引入了ThreadLocal;
二、ThreadLocal底层原理
首先ThreadLocal底层是基于五大引用中的其中一种弱引用;
2.1弱引用
弱引用(WeakReference)的特点:每次进行垃圾回收时,不管堆内存是否充足都会将弱引用的对象清理;此处也体现出ThreadLocal的生命周期一般不长,主要保存一些临时数据,例如:用户的登录数据信息;
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
2.2成员变量ThreadLocalMap
ThreadLocalMap是存在于ThreadLocal中的一个静态内部类,而在ThreadLocalMap中就存在着Entry继承了WeakReference,其就是弱引用;
2.3Thread中的ThreadLocalMap
在代码中我们也不难看出这个Entry的key就是ThreadLocal自身,value就是我们想要存放的数据了;
//与此线程相关的 ThreadLocal 值。此映射由 ThreadLocal 类维护。
ThreadLocal.ThreadLocalMap threadLocals = null;
我们通过源码可以查看到,Thread这个类中维护了ThreadLocalMap属性;
三、ThreadLocalMap将ThreadLocal实例作为key的好处
1.线程与线程之间的数据隔离(使用同一个ThreadLocal实例,不同的是每个Thread实例都有自己的ThreadLocalMap对象,不同线程之间是不能进行此数据的共享的,这样就实现了数据隔离);
2.此数据是由ThreadLocal维护的,我们在只需要操作ThreadLocal就能够管理不同线程之间的数据;
三、ThreadLocalMap作为Thread的成员变量所带来的问题
3.1问题
在上面我们了解到,Thread中存放着ThreadLocalMap,随着Thread的消失,ThreadLocalMap也会消失,但是面临一个问题,就是我们的Thread一般是交给线程池来管理,我们不可能用完之后就将Thread对象销毁,至少在核心线程中;所以不同用户可能使用同一个Thread对象,这样每个用户之间的数据隔离性就被打破了;
3.2如何解决?
其实很简单,我们只需要及时清理每个线程中的ThreadLocalMap数据不就行了,一般使用拦截器的后置处理;
四、早期ThreadLocal的对比
早期的ThreadLocal是根据Thread对象作为map的key的,这样也能实现线程间的数据隔离;但是存在致命的问题:
1.性能问题。(每来一个用户为其开辟一个Thread空间,存放到map中,底层也是数组的形式,数组是一块连续的内存空间,我们知道连续的内存空间的申请很影响性能)
2.hash冲突的影响,查询数据变慢(违背了设计ThreadLocal的初衷,ThreadLocal为的就是查询用户数据方便)
萌新一位,希望在以后的路上多多支持,点个赞吧~~~