Java——》ThreadLocal 本是古典 何须时尚 2024-03-04 05:21 65阅读 0赞 > 推荐链接: > [总结——》【Java】][Java] > [总结——》【Mysql】][Mysql] > [总结——》【Redis】][Redis] > [总结——》【Kafka】][Kafka] > [总结——》【Spring】][Spring] > [总结——》【SpringBoot】][SpringBoot] > [总结——》【MyBatis、MyBatis-Plus】][MyBatis_MyBatis-Plus] > [总结——》【Linux】][Linux] > [总结——》【MongoDB】][MongoDB] > [总结——》【Elasticsearch】][Elasticsearch] #### Java——》ThreadLocal #### * 一、概念 * 二、源码 * 三、内部结构 * 四、特点 * 五、内存泄漏问题 * * 1、现象 * 2、解决方案 * 六、内存泄漏案例 * 七、保证原子性 ## 一、概念 ## ThreadLocal可以理解为`线程本地变量`,他会在每个线程都`创建一个副本`,那么在线程之间访问内部副本变量就行了,做到了线程之间互相`隔离`,相比于synchronized的做法是用空间来换时间。 ThreadLocal的本质就是一个`Map`,ThreadLocal做为key,将一个数据和本地线程绑定在一起。 ## 二、源码 ## ThreadLocal有一个`静态内部类ThreadLocalMap`,ThreadLocalMap又包含了一个`Entry数组`,Entry本身是一个`弱引用`,他的key是指向ThreadLocal的弱引用,Entry具备了保存key value键值对的能力。 ![image.png][] ![image.png][image.png 1] ## 三、内部结构 ## ![image.png][image.png 2] ## 四、特点 ## * 每个Thread中都存储着一个成员变量ThreadLocalMap * ThreadLocal本身不存储数据,像是一个工具类,基于ThreadLocal去操作ThreadLocalMap * ThreadLocalMap本身就是基于Entry\[\]实现的,因为一个线程可以绑定多个ThreadLocal,这样一来,可能需要存储多个数据,所以采用Entry\[\]的形式实现。 * 每一个现程都自己独立的ThreadLocalMap,再基于ThreadLocal对象本身作为key,对value进行存取 * ThreadLocalMap的key是一个`弱引用`,弱引用的目的是为了`防止内存泄露`,如果是强引用那么ThreadLocal对象除非线程结束否则始终无法被回收,弱引用则会在下一次GC的时候被回收 ## 五、内存泄漏问题 ## > Java中4种引用: > 强引用:OOM也不清除 > 软引用:内存不足清除 > 弱引用:只要GC就清除 > 虚引用:拿不到引用,构建出来就凉凉~~ ![image.png][image.png 3] ### 1、现象 ### 假如ThreadLocal对象被回收之后,key因为弱引用也会被GC回收掉,同时线程还没有被回收,entry中就存在key为null,但value有值的entry对象,但是内存中的value无法被获取到,同时也无法被回收,就会导致内存泄漏。 ### 2、解决方案 ### 使用TheadLocal完毕后,调用`remove方法删除Entry对象`。 ![image.png][image.png 4] ## 六、内存泄漏案例 ## > 参考链接:[Java——》内存泄露案例][Java 1] ## 七、保证原子性 ## ThreadLocal保证原子性的方式,是`不让多线程去操作临界资源`,`让每个线程去操作属于自己的数据`。 static ThreadLocal tl1 = new ThreadLocal(); static ThreadLocal tl2 = new ThreadLocal(); public static void main(String[] args) { tl1.set("123"); tl2.set("456"); Thread t1 = new Thread(() -> { System.out.println("t1:" + tl1.get()); System.out.println("t1:" + tl2.get()); }); t1.start(); System.out.println("main:" + tl1.get()); System.out.println("main:" + tl2.get()); } [Java]: https://blog.csdn.net/weixin_43453386/article/details/84788317 [Mysql]: https://blog.csdn.net/weixin_43453386/article/details/88667709 [Redis]: https://blog.csdn.net/weixin_43453386/article/details/127966762 [Kafka]: https://blog.csdn.net/weixin_43453386/article/details/128189472 [Spring]: https://blog.csdn.net/weixin_43453386/article/details/124900806 [SpringBoot]: https://blog.csdn.net/weixin_43453386/article/details/84788714 [MyBatis_MyBatis-Plus]: https://blog.csdn.net/weixin_43453386/article/details/84788053 [Linux]: https://blog.csdn.net/weixin_43453386/article/details/89241912 [MongoDB]: https://blog.csdn.net/weixin_43453386/article/details/84788450 [Elasticsearch]: https://blog.csdn.net/weixin_43453386/article/details/108583782 [image.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/3475d6289d564e7da6134ead5ee176a6.png [image.png 1]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/2feac09d04554ff3b002e64511742002.png [image.png 2]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/ea38c961091243279919d10eae770fff.png [image.png 3]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/2d025d59cb0940ccbd9649be144479cd.png [image.png 4]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/280d4da939f443f9962164045c27c40b.png [Java 1]: https://blog.csdn.net/weixin_43453386/article/details/124392284
还没有评论,来说两句吧...