ThreadLocal学习
面试题总结
1、TreadLocal到底是干什么的?
ThreadLocal是为了做线程隔离的,就是线程之间互不干扰,它是一个数据结构,有点像HashMap,可以保存"key : value"键值对,但是一个ThreadLocal只能保存一个,并且各个线程的数据互不干扰。
线程可以理解为人,那么张三和李四要动用同一个钱包(不同线程处理相同的变量),可以将钱包(变量)复制一份,具体的例子如下:
比如多个线程执行 int num = 0 ;num += 5;使用ThreadLocal之后,每个线程之间操作的num就不会互相影响,每一个线程拿到的num=5, 没有ThreadLocal的话,有些线程就会在其他线程的基础上加上5,最终拿到的就有可能是5,10, 15, 20…
2、ThreadLocal的底层数据结构是什么?
就是一个Hash表
Hash表就是,因为我们的数组下标是通过hash值计算而来的,所以,当前这个数组叫做Hash表
3、ThreadLocal的底层中Hash数组的默认长度是多少?
16
4、ThreadLocal当容量达到多少时,会触发扩容?
扩容因子: 2/3 ,注意(HashMap的扩容因子是0.75)
为什么是2/3,如果太小的话,就会造成数组的频繁扩容,如果太大的话,就会浪费数组的内存空间
5、hashcode是一个int类型的数据,这个int类型的数据长度是32位?
00000000 00000000 00000000 00000000
怎么计算hashcode , 取模
6、ThreadLocal如何处理hash冲突的呢?
线性探测法
7、ThreadLocal的hashcode是通过一个魔数来计算的,通过斐波那契额散列求出来的
魔数= 黄金分割比(0.618) * 2 ^ 32
8、ThreadLocal的Map数组的长度为什么一定要确保是2的幂次方呢?
为了减少hash冲突
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
上面这个代码就是为了计算数组的下标(通过hashcode 于数组长度减一相与)
32为的hashcode中低4位表示数组的下标
比如一个hashcode如下:
01010011 10000100 01011001 100000100 (2的次幂形式都是1,比如1111)
相与的话
01010011 10000100 01011001 10000**
0100
**& 1111
0100 这样子最后四位就不会变
但如果不是2的次幂这种1111的形式的话,最后得到后四位相与的结果就会发生变化:
01010011 10000100 01011001 100000100 (2的次幂形式都是1,比如1111)
相与的话
01010011 10000100 01011001 10000**
0100
**& 1011
0000 会发现原本hashcode的后四位是0100,现在结果变为了 0000
9、java中有几种引用类型?
强引用:Object obj = new Object(); 当对象被强引用关联的时候,不管你内存充不充足,垃圾回收的时候都不会回收
软引用:当垃圾回收的时候,如果内存充足,则不会回收该对象,如果内存不足了,则会回收
弱引用:当垃圾回收的时候,不管内存充不充足,都会回收
虚引用:
10、ThreadLocal中的Key值使用的是弱引用,为什么要使用弱引用?
为了减少内存泄漏问题,如果是强引用的话,不会回收内存,内存被回收不了,就会造成内存泄漏
11、Key使用了弱引用,为什么还会出现内存泄漏的问题呢?
因为Map中的value依然使用的是强引用,回收不了,会造成内存泄漏
那为什么value不像key一样使用弱引用?
value不值设置为弱引用,否则假如value被回收了,key还在的话,会出现map.get(key) =null
12、如何彻底解决内存泄漏问题?
解决办法是每次使用完ThreadLocal都调用它的remove()方法清除数据,或者按照JDK建议将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用,也就能保证任何时候都能通过ThreadLocal的弱引用访问到Entry的value值,进而清除掉。
13、ThreadLocal怎么使用呢?
1、创建对象 ThreadLocal girl = new ThreadLocal():
2、girl.set();
3、girl.get();
replaceStaleEntry
1、清理一下无效的节点(Entry(null, 2)), Entry中的key为null的这一类
2、进行线性探测,存数据
14、ThreadLocal的set和get方法
set
get
15、ThreadLocal和Synchonized
两者都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。Synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
16、ThreadLocal中的key和value
dLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
2022-07-02