美文网首页
Java并发编程-ThreadLocal

Java并发编程-ThreadLocal

作者: agile4j | 来源:发表于2019-04-02 22:18 被阅读0次

    1.注意事项

    • 使用ThreadLocaL时要注意:为每个线程分配一个对象的工作并不是由ThreadLocal来完成的,而是需要在应用层面保证的。如果在应用层为每个线程都分配了同一个对象实例,那么ThreadLocal也不能保证线程安全。

    2.实现原理

    • ThreadLocal的实现原理:分两步,第一步是从当前线程对象,拿到到ThreadLocalMap对象(是Thread对象的一个名为threadLocals的成员变量);第二步是根据ThreadLocalMap对象维护的映射关系,由当前ThreadLocal对象(作为key),得到value。(注意,ThreadLocalMap类并没有实现Map接口,但从功能上可以理解为一个Map)
      ThreadLocal(1).png-30.3kBThreadLocal(1).png-30.3kB

    3.清理工作

    • 通过ThreadLocal的实现原理,我们可以发现,这些变量都是维护在Thread类内部的,这也就意味着只要线程不退出,对象的引用就一直存在。
    • 而当我们使用线程池时,就意味着当前线程未必会退出,这种情况下,如果我们将一些很大的对象设置到ThreadLocal中,就会使系统出现内存泄漏的可能(这个对象已经不再有用了,但却无法被回收)。
    • 清理ThreadLocal有两种方式:

    1.使用ThreadLocal.remove()方法

    • 使用ThreadLocal.remove()方法移除变量,这就像我们习惯性地关闭数据库连接一样,如果确定不需要这个对象了,那么就应该告诉虚拟机,请把它回收掉,防止内存泄漏。

    2.手动将ThreadLocal对象置为null

    • 手动将ThreadLocal对象置为null,例如threadLocal=null,那么这个ThreadLocal对应的所有线程的局部变量都有可能被回收。
    • 之所以可以这样,这是因为ThreadLocalMap的实现使用了弱引用(ThreadLocalMap非常类似于WeakHashMap)。弱引用就是比强引用弱得多的引用。Java虚拟机在垃圾回收时,如果发现弱引用,就会立即回收。ThreadLocalMap内部由一系列Entry构成,每一个Entry都是WeakReference<ThreadLocal>:
    static class Entry extends WeakReference<ThreadLocal<?>> {
        /** The value associated with this ThreadLocal. */
        Object value;
    
        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
    
    • 因此,虽然这里使用ThreadLocal作为Map的key,但实际上,它并不真的持有ThreadLocal的引用。而当ThreadLocal的外部强引用被回收时,ThreadLocalMap中的key就会变成null。当系统进行ThreadLocalMap 清理 时(比如将新的变量加入表中,就会自动进行一次清理),就会自然将这些垃圾数据回收:
      ThreadLocal的回收机制.png-159.6kBThreadLocal的回收机制.png-159.6kB

    END

    参考资料:《实战Java高并发程序设计》

    相关文章

      网友评论

          本文标题:Java并发编程-ThreadLocal

          本文链接:https://www.haomeiwen.com/subject/wfxobqtx.html