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 而言是存在冗余的,因此也造成了一定的浪费。

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

  • 相关阅读:
    利用DTrace实时检测MySQl
    改进MySQL Order By Rand()的低效率
    RDS for MySQL查询缓存 (Query Cache) 的设置和使用
    RDS For MySQL 字符集相关说明
    RDS for MySQL 通过 mysqlbinlog 查看 binlog 乱码
    RDS for MySQL Mysqldump 常见问题和处理
    RDS for MySQL Online DDL 使用
    RDS MySQL 表上 Metadata lock 的产生和处理
    RDS for MySQL 如何使用 Percona Toolkit
    北京已成为投融资诈骗重灾区:存好骗子公司黑名单,谨防上当!
  • 原文地址:https://www.cnblogs.com/cpcpp/p/15212445.html
Copyright © 2011-2022 走看看