如果防止本地线程的变量被其他线程修改?
我们的想法就是一个线程创建一个实例对象,但是这样会引起几个问题:什么时候创建?什么时候销毁?哪些线程需要创建?
而ThreadLocal实现了“防止本地线程的变量被其他线程修改”,同时避免处理“什么时候创建?什么时候销毁?哪些线程需要创建?”的一系列问题。
ThreadLocal是一个数据结构,是一个HashMap,每个线程在用到的时候会实例化。
具体用法很简单,我们只需要在全局声明一个ThreadLocal变量。然后所有线程最开始访问这个变量的时候,都只会返回null,而之后对这个变量赋值后,有且只有当前线程能够访问和修改上一次赋的值。
知道了这个定义后,下面就是罗列考点了。
---------
一个“看起来好像不怎么优雅的结构”ThreadLoalMap
每一个线程对象Thread 内部都有一个
ThreadLoalMap引用,在首次使用的地方会被初始化(其实就在ThreadLocal实例Get()的时候)。
ThreadLoalMap就好像是每个线程的私有堆空间一样,只有该线程能访问得到,当你ThreadLocal实例Get()的时候,就会获取这块私有线程堆空间,他会把ThreadLocal对象当做Key从堆空间获取该线程特殊持有的变量。其实这块堆空间就是一个特殊的哈希表,有什么特殊之处呢?这是下一个考察点。
------
ThreadLoalMap怎么解决哈希冲突?
和hashMap不同,ThreadLoalMap没有链表结构,当发生冲突的时候他会在哈希表上按顺序查找下一个空位,这意味着,当发生冲突的时候,ThreadLoalMap的插入效率很低,通时查询性能也很低。(性能这么渣好想优化他是吗?)
------
会内存泄漏吗?
虽然Key被保存在WeakReference中,WeakReference是弱引用,在外部没有强引用的情况下可以被GC,但是可恶的在于Entry对Value进行了强引用,所以即使外部没有强引用,Value依然得不到释放导致内存泄漏。
所以在用完ThreadLocal后你还是得乖乖的使用 threadLocal.set(null);或者 threadLocal.remove(); 对ThreadLocal对象进行内存释放,否则就会内存泄漏了。
ThreadLocal这也是使用时候必须记住的要点。