zoukankan      html  css  js  c++  java
  • 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 而言是存在冗余的,因此也造成了一定的浪费。

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

  • 相关阅读:
    Ansible 利用playbook批量部署mariadb
    Win10系统 安装Anaconda+TensorFlow+Keras
    keras中7大数据集datasets介绍
    新闻分类:多分类问题
    机器学习之SVM多分类
    机器学习之多分类学习
    机器学习(经典博客)
    机器学习实战
    多元函数的极值分析
    一元函数、多元函数的泰勒公式
  • 原文地址:https://www.cnblogs.com/cpcpp/p/15212445.html
Copyright © 2011-2022 走看看