ThreadLocal使用方法及存在问题

ThreadLocal使用场景:
1.解决线程安全问题
2.实现线程级别的数据传递

ThreadLocal缺点:
1.不可继承性:子线程中不能读取到父线程的值 InheritableThreadLocal() 不能实现不同线程之间的数据共享
2.脏读(脏数据): 在一个线程中读取到了不属于自己的数据 。
线程使用 ThreadLocal 不会出现脏读,每个线程都是用的是自己的变量值和 ThreadLocal
线程池使用 ThreadLocal 会出现脏数据,线程池会复用线程,复用线程之后,也会复用线程中的静态属性,从而导致某些方法不能被执行,于是就出现了脏数据的问题
3.ThreadLocal 内存溢出问题(最常出现的问题)
内存溢出:当一个线程执行完之后,不会释放这个线程所占用内存,或着释放内存不及时(线程不用了,但线程相关内存还得不到及时释放)


脏数据解决方案:
1.避免使用静态属性(静态属性在线程池中会复用)
2.使用remove解决

 

ThreadLocal的原理:
ThreadLocal的set实际实在当前线程对象里创建了一个内部变量ThreadLocalMap<ThreadLocal,object> ,ThreadLocalMap的key是ThreadLocal的引用。

造成泄漏的原因:
由于ThreadLocal对象是弱引用,如果外部没有强引用指向它,它就会被GC回收,导致Entry的Key为null

如果当前的情况下在栈中将threadlocal1的引用设置为null,强引用1将会失效,那堆中的threadlocal1对象因为ThreadLocalMap的key对它的引用是弱引用,将会在下一次gc被回收,那就会出现key变成null,如果这时value外部也没有强引用指向它,那么value就永远也访问不到了,按理也应该被GC回收,但是由于ThreadLocalMap.Entry对象还在强引用value,导致value无法被回收,这时「内存泄漏」就发生了,value成了一个永远也无法被访问,但是又无法被回收的对象。

解决办法:
1:将ThreadLocal设置为空之前,执行remove()方法,会将key为空的键值对清空

2:尽量将ThreadLocal设置成static

3: 非必要尽量不要在ThreadLocal中放大对象

posted @ 2023-02-24 15:06  景恩  阅读(1057)  评论(0编辑  收藏  举报