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,threadLocalRef被回首时,因为threadLocalMap的Entry使用了强引用,造成key无法回收。
如果没有手动删除Entry以及CurrentThread依然运行的前提下,始终有强引用链,导致内存泄漏
 
为什么使用弱引用?
当threadLocalRef被回收时,因为是弱引用会将key值进行回收,代码中,get、set、remove方法中会进行判断,如果key为null,会将当前entry删除(get、set,只用下一次调用时才会执行)
 
如何解决threadLocal的内存泄漏问题?
1.当使用完threadLocal时,手动调remove方法,删除对应的entry
2.当threadLocal使用结束时,如果当前thread也随之结束,threadLocalMap自然就会被gc回收,从根源解决了内存泄漏(threadLocalMap是thread的一个属性)

 

ThreadLocal的应用场景?

  线程安全:ThreadLocal用于保存每个线程独享对象,为每个线程都创建一个副本,确保线程安全。

  参数传递:ThreadLocal用作每个线程内需要独立保存上下文参数,方便其他方法获取这些上下文。在多层架构中,使用较多。

 

ThreadLocal扩容机制?

当table中Entry的数量size>=threshold*3/4时,需要对table进行2倍扩容。扩容的原因:降低哈希冲突

 

强引用、软引用、弱引用、虚引用

强引用:GC回收时不会强制回收,及时内存溢出也不会进行强制回收。例如:new对象

软引用:当内存不足时,GC会强制回收。用来描述一些不是必须的对象

弱引用:GC时无论内存是否充足,都会强制回收

虚引用:不影响对象的生命周期,在任何时候都可能被GC期回收

 

ThredaLocal有那些注意事项?

不要使用ThreadLocal存储大对象

注意使用ThreadLocal的remove方法,清理过期数据,否则会产生大量脏数据,内存泄漏等问题

使用private final static 进行修饰,防止多实例时内存的泄漏问题

 

 
posted @ 2020-10-16 17:22  蹦蹦郭  阅读(209)  评论(0编辑  收藏  举报