1.threadlocal生命周期
随着threadlocal的new产生,随着线程的总结而结束
随着threadlocal的new产生,随着调用remove方法而结束
2.Thread里边包含了两个属性
threadLocals
inheritableThreadLocals 一般用于父子线程
这两个属性都是 Threadlocal.ThreadlocalMap
3.Threadlocal为 threadlocals的一个key值 ,一个键值对为 Entry ,Entry是弱引用,弱引用特点:GC回收时只要只有弱引用指着那就会回收掉这个对象。
4.Threadlocal应用场景 事务管理 定义类成员变量(静态和普通)
5.为什么设置为弱引用,value为什么不是
设为弱引用是为了防止内存泄漏的一种,在threadlocal生命周期结束后(线程结束或者手动设为null),threadlocal设为null,因为entry的key为弱引用,所以GC回收时会回收掉这部分引用,降低内存泄漏的风险,但是这个时候value是强引用,还没有被回收,所以一定要调用remove方法回收掉value。
这里value为什么不设为弱引用,举个例子value是在局部块声明的,局部方法结束后,局部变量value就变成了null,如果entry的value设置为弱引用,那么GC回收时就会被回收掉,在下一个方法取值时会取为null,业务就得不到满足。而entry的key是threadlocal,是随着线程的生命周期进行的,除非手动设为null,所以key值设为null好处在于减少内存泄漏的风险。
set,get,remove方法当key为null时,其实是会处理value的回收的。包括ThreadlocalMap也有惰性机制去处理key为null的entry的。
6.API
set
get
remove 移除当前threadlocal的entry
withInitial 生成一个带有初始值的threadlocal
initialValue : get第一次调用,返回null
7.set(null)和remove有什么区别
set(null)是将value设置了null,但是entry还存在,remove是将entry设为null
8.为什么会有内存泄漏
一般都是因为没有remove,value没有被回收
9.线程池问题
要注意线程复用导致threadlocal被复用,所以使用线程池最好每次线程结束后将threadlocal remove掉,或者直接将MAP设为null,减少MAP的空间
10.为什么ThreadlocalMap的键值对要用entry,而不是hashmap
减少哈希碰撞
减少内存泄漏的风险