jdk-ThreadLocalMap
2021-07-20 11:51:14 0 举报
ThreadLocal,ThreadLocalMap,Thread
作者其他创作
大纲/内容
v指向的真正的实例对象
为什么内存泄漏?使用线程池的时候,线程是不会回收的,而map是被强引用,所以map和线程一起死亡,假如作为一个JDBC连接池工具类,每次获取JDBC连接的时候都使用局部变量指向新建ThreadLocalA实例,而不是全局的static变量,执行结束,方法弹栈。线程还在,但是没有强引用只剩下Entry这个弱引用指向堆里面的实例的时候,v对真正实例是强引用,此时获取不到这个对象,因为k已经指向null了,对应的v有指向你也拿不到,又不能回收,因为v引用着,这就泄漏了
entry
ThreadLocalMap1实例
获取不到又不能释放
第一次ThreadLocal.set方法触发map的创建
Entry 是弱引用,指向的对象是什么无所谓,自己是弱引用,自己引用的对象GC的时候无法保证其不被回收
Thread 2
内存泄漏是因为弱引用吗?不是,弱引用反而是减少了泄漏,ThreadLocal因为只是被弱引用所以可回收,最后只剩下一个value的强引用,否则的话Key也会泄漏,不只是value泄漏了,还有一个好处就是弱引用指向的null之后,有利于get set remove方法找到对应的泄漏的value变为null,解决value的内存泄漏问题
Thread 1 的虚拟机栈
内存泄漏?
一个应用:在写Spring的web项目的时候应用:这个一般用作UserModelContext,也就是存放一个特定用户的信息,TheadLocal实例是spring启动的时候作为Bean给工厂管理的,一个请求过来就是一个新的线程,会使用这个Bean实例创建线程专属的map实例之后,使用set在对应index存用户信息,后面就和下面的一样了。(Spring管理的ThreadLocal,工厂对ThreadLocal一直是有一个强引用的,也就是每个线程的threadLocals的Entry 指向的key不会被回收,但是请求离开的时候还是要remove,因为以后不会用了,防止map的数组不断扩容,最后还是会内存泄漏,虽然不是上面的那种变为null的内存泄漏,但是终归是不会去再次获取了)意义:一个属于当前线程的变量,不用通过方法参数频繁传递,而且是每个线程相互隔离的
Thread 1
维护的数组
k:指向堆里面的同一个ThreadLocalA实例v: 线程传递进来的值1
ThreadLocalMap2实例
原理
1 新建专属于Thread 2
k:指向nullv: 线程传递进来的值1
为什么说同一个ThreadLocal在不同的线程里面有不同的值?就是因为不同线程有不同的map,map里面的key是同一个ThreadLocal,但是值却不一样
k:指向堆里面的同一个ThreadLocalA实例v: 线程传递进来的值3
堆
成员变量threadLocals
1 新建专属于Thread 1
Thread 2 的虚拟机栈
Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value永远无法回收,造成内存泄漏。
唯一的ThreadLocalA实例
0 条评论
下一页