ThreadLocal
ThreadLocal数据结构
JDK8设计是此方案,早期设计是:key存的是thread,以threadLocal为单位。
JDK8设计的好处:当thread销毁时,tthreadLocalMap也会随之销毁,减少内存的使用。
内存引用流程图
什么是ThreadLocal?有什么特性?
ThreadLocal是线程变量,ThreadLocal中设置的变量属于当前线程,该变量对其它线程而言是隔离的。
特性:
并发性:多线程并发场景下使用。传递数据:可以通过ThreadLocal在同一线程的上下文中传递参数。线程隔离:每个线程都是独立的,不相互影响。
ThreadLocalMap初始化大小、加载因子是多少?
初始化大小是16,加载因子为2/3。HashMap的加载因子是0.75(加载因子越大,装载的越多,hash冲突的可能性越大,反之装载的越少,hash冲突可能性越小,内存使用率不高)
ThreadLocal底层的hash算法?
底层使用斐波那契数(黄金分割数)来实现hash算法。ThreadLocal有属性HASH_INCREMENT(斐波那契数),每当创建一个ThreadLocal对象,它的下一个hashCode就会增长0*61c88647
ThreadLocalMap如何解决hash冲突?
ThradLocalMap使用开放地址(线性探测)解决hash冲突,HashMap用链地址法解决冲突。
开放地址法(线性探测法):ThreadLocalMap根据初始key的哈希值确定元素在table数组中的位置,如果发现这个位置已经被其他key值占用,则利用固定的算法寻找一定步长的下个位置,直到找到能够存放的位置。
常用解决hash冲突的方法:开放地址法(线性探测法、平法探测法、双散列函数探测法);
链地址法:将所有哈希地址为i的元素构成一个称为同义词的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、删除、插入主要在同义词链中进行,适用于经常插入和删除的情况;
再哈希:同时构造多个不同的哈希函数,第一个冲突使用第二个,以此类推;
如果使用强引用会怎么样?:
ThreadLocal的应用场景?
线程安全:ThreadLocal用于保存每个线程独享对象,为每个线程都创建一个副本,确保线程安全。
参数传递:ThreadLocal用作每个线程内需要独立保存上下文参数,方便其他方法获取这些上下文。在多层架构中,使用较多。
ThreadLocal扩容机制?
当table中Entry的数量size>=threshold*3/4时,需要对table进行2倍扩容。扩容的原因:降低哈希冲突
强引用、软引用、弱引用、虚引用
强引用:GC回收时不会强制回收,及时内存溢出也不会进行强制回收。例如:new对象
软引用:当内存不足时,GC会强制回收。用来描述一些不是必须的对象
弱引用:GC时无论内存是否充足,都会强制回收
虚引用:不影响对象的生命周期,在任何时候都可能被GC期回收
ThredaLocal有那些注意事项?
不要使用ThreadLocal存储大对象
注意使用ThreadLocal的remove方法,清理过期数据,否则会产生大量脏数据,内存泄漏等问题
使用private final static 进行修饰,防止多实例时内存的泄漏问题