ThreadLocal看完你就明白了(二)

ThreadLocal看完你就明白了(二)

大家好,我是栗子为

上次和大家聊完ThreadLocal相关的基础知识,今天打算做个了结,我们一起拿下这个面试高频题,结合上一篇文章,希望大家在面试中回答得都能游刃有余

我们从一个概念内存泄漏开始说起



01


什么是内存泄露?

不再会被使用的对象和变量所占用的内存不能得到回收,这就是内存泄露



02


为什么会有内存泄露的问题?


这就要从ThreadLocalMap的数据结构说起….

我们一起看看ThreadLocalMap的结构,正好回顾上一篇的内容

ThreadLocalMap从字面上就可以看出这是一个保存ThreadLocal对象的map(Key为ThreadLocal,value为任意对象),经过两层包装后的ThreadLocal对象:

  1. 第一层包装使用了WeakReference<ThreadLocal<?>>将ThreadLocal对象变成一个弱引用对象
  2. 第二层包装是定义了一个专门的类Entry来扩展WeakReference<ThreadLocal<?>>
ThreadLocal看完你就明白了(二)
ThreadLocalMap底层源码



03


四大引用


我们一直都会提到弱引用,那到底什么是弱引用呢,还有哪几种引用呢?

别着急,我们一起往下看

我们通常所说的引用有如下四种:

  • 强引用:我们通常使用new创建的对象就是强引用,这是默认一种引用,不管内存是否够用,GC不会回收强引用的对象

  • 软引用(SoftReference):只要内存够用,就不会回收软引用对象,当内存不够用的时候,GC会回收软引用对象,通常与内存敏感的数据都会作为软引用

  • 弱引用(WeakReference):只要被GC发现弱引用,不管内存是否够用,都会进行回收,可以与队列结合使用,举个弱引用的场景:如果一个请求要读取大量的图片,采用从硬盘读取的方式会带来效率低的问题,采用从内存读会带来内存不足的问题,所以这个时候就可以采用弱引用的方式,及时回收内存,避免OOM问题

  • 虚引用(PhantomReference):

    • 虚引用必须要和引用队列(ReferenceQueue)联合使用

      虚引用顾名思义,就是形同虚设,与其他几种引用不同,它不会决定对象的生命周期。如果一个对象仅是虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收,不能单独使用,也不能访问对象,必须和引用队列一起使用

    • PhantomReference的get方法总是返回null

      虚引用主要用来跟踪对象被垃圾回收的状态。仅仅是提供一种确保对象被finalize之后做一些通知,它无法访问对应的引用对象

    • 处理监控通知使用

      它是一种比finalize机制更灵活的回收操作,可以在对象被回收的时候收到一个系统通知或后续更进一步的处理

那么问题来了,为什么ThreadLocal要采用弱引用呢?



04


为什么要采用弱引用?


我们结合代码来理解

ThreadLocal<String> t = new ThreadLocal<>();  // 强引用
t.set("sixchestnuts");
t.get();

这段代码对应的引用关系如下:

ThreadLocal看完你就明白了(二)
引用关系

当线程执行完,栈帧消耗,那么对应的局部变量强引用t也不存在,此时:

如果Key是强引用,则导致被Key指向的ThreadLocal对象不能被回收

如果Key是弱引用,就会大概率减少内存泄露的问题,同时当方法执行完毕,ThreadLocal对象被回收,Entry的Key指向null,这样会出现一个问题就是会存在大量的Key为Null的Entry,导致内存泄露,所以我们要手动调用remove方法



05


总结


在网上翻阅资料的时候看到了一个针对于在开发过程中使用ThreadLocal的小trick,在这里分享给大家:

  1. ThreadLocal.withInitial(()->初始值)
  2. 把ThreadLocal修饰为static,因为它只是一个壳子,真正是内部的ThreadLocalMap,所以只需要初始化一次,分配一块存储空间就够了
  3. 使用完后手动remove

说完小技巧,总结一下关于ThreadLocal的知识点:

  1. 它不是用来做线程间数据共享的
  2. 适用于变量在线程间隔离,且在方法间共享的场景
  3. ThreadLocal通过隐式的在线程内部创建变量副本从而避免了实例的线程安全问题
  4. ThreadLocalMap中Entry的键对ThreadLocal是弱引用,避免ThreadLocal对象无法被回收的问题

以上就是关于ThreadLocal的所有内容啦,感谢坚持到最后的你们,希望大家都能早日拿到心仪的offer

我们下次再见~

关注六只栗子,面试不迷路~

作者    栗子为

编辑   一口栗子  

ThreadLocal看完你就明白了(二)

ThreadLocal看完你就明白了(二)

ThreadLocal看完你就明白了(二)

ThreadLocal看完你就明白了(二)



原文始发于微信公众号(六只栗子):ThreadLocal看完你就明白了(二)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/88310.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!