• Java并发--ThreadLocal


    ThreadLocal 用于存储线程私有的对象。

    查看 Thread 类的源码可以发现,每个 Thread 对象中都会有一个 ThreadLocalMap 的属性,它是一个 HashMap 结构, key 是 ThreadLoacl 对象, value 是该 ThreadLocal 存储的 Object。

    线程初始时,ThreadLocalMap 是空的,当我们需要为线程设置它的私有对象时,可以新建一个 ThreadLocal 对象,像这样:

    ThreadLocal<Object> threadLocal = new ThreadLocal<Object>();
    

    它的主要方法有:

    public T get() { }  
    public void set(T value) { }  
    public void remove() { }  
    protected T initialValue() { } 
    

    然后可以通过 set 方法放进去一个对象,可以通过 get 方法获取对象。

    我们来看一张图就清晰了。

    ThreadLocal 和它的 Object 就是存在了该线程的 ThreadLocalMap 中,所以很明显是线程私有的。

    如果线程挂了,ThreadLocalMap 失去引用,就会被回收掉。

    • 弱引用问题

      ThreadLocalMap 中用到了弱引用,ThreadLocalMap 的 Entry 中 key 是 ThrealLocal 对象, value 是 ThrealLocal 对象所对应的 Object。如果出现这样的情况:程序中的 ThreadLocal 对象失去了强引用,但是 key 仍然持有对它的引用,如果这个引用是强引用,ThreadLocal 将永远不会被回收。因此这里设计者把 key 对 ThreadLocal 的引用设置为了弱引用。(个人认为这里是防止了ThreadLoacl对象无法回收导致的内存泄露,下小节讲的是Object对象产生的内存泄露)

    • 内存泄露问题

      如果线程一直活着,但是 ThreadLocal 因为一些操作导致失去了强引用,那么它就会被回收。那么将导致 ThreadLocalMap 中存在 <null, Object> 的键值对,即内存泄露了。

      所以在使用完 ThreadLocal 后,应该调用 remove 主动移除ThreadLocalMap 中的键值对。

    • 使用注意

      一般我们把 ThreadLocal 定义为 static(这是JDK的推荐),因为如果ThreadLocal 是实例属性,那么在线程中每创建一个这个类的实例,就也会新建一个 <ThreadLocal, Object>, 对于 Object 而言是存在冗余的,因此也造成了一定的浪费。

    *关于内存泄露这块感觉理解还不是很深,主要是没有结合实际生产案例。

  • 相关阅读:
    解决:Ubuntu12.04下使用ping命令返回ping:icmp open socket: Operation not permitted的解决
    【Magenta 项目初探】手把手教你用Tensorflow神经网络创造音乐
    python表达式操作符【学习python必知必会】
    关于提高python程序执行效率的思路和想法
    动手前的构思在编写程序中的重要性
    python 之禅
    HTTP 访问学习笔记 留坑
    软件工程与方法学——面向对象程序设计例子
    python 英文字串首字母改为大写
    Objective-C:方法缓存
  • 原文地址:https://www.cnblogs.com/cpcpp/p/15212445.html
Copyright © 2020-2023  润新知