• ThreadLocal学习笔记


    参考博客:

    ThreadLocal-面试必问深度解析 https://www.jianshu.com/p/98b68c97df9b
    面试官:知道ThreadLocal嘛?谈谈你对它的理解?(基于jdk1.8) https://baijiahao.baidu.com/s?id=1653790035315010634&wfr=spider&for=pc
    软引用、弱引用、虚引用-他们的特点及应用场景 https://www.jianshu.com/p/825cca41d962
    ThreadLocal https://www.jianshu.com/p/3c5d7f09dfbd

    • 每个Thread线程内部都有一个Map
    • Map里面存储 ThreadLocal(key)和线程的变量副本(value)
    • 多个 ThreadLocal 可以保存多个变量

    Hash冲突怎么解决

    • 和HashMap使用拉链法不同,ThreadLocalMap使用线性探测法处理Hash冲突。
    • 所谓线性探测,就是根据初始key的hashcode值确定元素在table数组中的位置,如果发现这个位置上已经有其他key值的元素被占用,则利用固定的算法寻找一定步长的下个位置,依次判断,直至找到能够存放的位置。
    • ThreadLocalMap解决Hash冲突的方式就是简单的步长加1或减1,寻找下一个相邻的位置。
    • 所以这里引出的良好建议是:每个线程只存一个变量,这样的话所有的线程存放到map中的Key都是相同的ThreadLocal,如果一个线程要保存多个变量,就需要创建多个ThreadLocal,多个ThreadLocal放入Map中时会极大的增加Hash冲突的可能。
     
    /**
     * Increment i modulo len.
     */
    private static int nextIndex(int i, int len) {
        return ((i + 1 < len) ? i + 1 : 0);
    }
    
    /**
     * Decrement i modulo len.
     */
    private static int prevIndex(int i, int len) {
        return ((i - 1 >= 0) ? i - 1 : len - 1);
    }

    内存泄漏问题

    https://blog.csdn.net/qq_42862882/article/details/89820017

    注意!假如每个key都强引用指向threadlocal,也就是上图虚线那里是个强引用,那么这个threadlocal就会因为和entry存在强引用无法被回收!造成内存泄漏 ,除非线程结束,线程被回收了,map也跟着回收。

    依然出现的内存泄露问题

    虽然上述的弱引用解决了key,也就是线程的ThreadLocal能及时被回收,但是value却依然存在内存泄漏的问题。

    当把threadlocal实例置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal将会被gc回收.

    map里面的value却没有被回收.而这块value永远不会被访问到了. 所以存在着内存泄露,

    因为存在一条从current thread连接过来的强引用.

    只有当前thread结束以后, current thread就不会存在栈中,强引用断开, Current Thread, Map, value将全部被GC回收.

    所以ThreadLocal使用完了,应调用threadlocal的remove方法,而不是把它设为null。

    弱引用

    下面一段话摘自《Java核心技术卷1》:

    设计 WeakHashMap类是为了解决一个有趣的问题。如果有一个值,对应的键已经不再 使用了, 将会出现什么情况呢? 假定对某个键的最后一次引用已经消亡,不再有任何途径引 用这个值的对象了。但是,由于在程序中的任何部分没有再出现这个键,所以,这个键 / 值 对无法从映射中删除。为什么垃圾回收器不能够删除它呢? 难道删除无用的对象不是垃圾回 收器的工作吗?

    遗憾的是,事情没有这样简单。垃圾回收器跟踪活动的对象。只要映射对象是活动的, 其中的所有桶也是活动的, 它们不能被回收。因此,需要由程序负责从长期存活的映射表中 删除那些无用的值。 或者使用 WeakHashMap完成这件事情。当对键的唯一引用来自散列条
    目时, 这一数据结构将与垃圾回收器协同工作一起删除键 / 值对。

    下面是这种机制的内部运行情况。WeakHashMap 使用弱引用(weak references) 保存键。 WeakReference 对象将引用保存到另外一个对象中,在这里,就是散列键。对于这种类型的 对象,垃圾回收器用一种特有的方式进行处理。通常,如果垃圾回收器发现某个特定的对象 已经没有他人引用了,就将其回收。然而, 如果某个对象只能由 WeakReference 引用, 垃圾 回收器仍然回收它,但要将引用这个对象的弱引用放人队列中。WeakHashMap将周期性地检 查队列, 以便找出新添加的弱引用。一个弱引用进人队列意味着这个键不再被他人使用, 并 且已经被收集起来。于是, WeakHashMap将删除对应的条目。

    虚引用
     
    jdk中直接内存的回收就用到虚引用,由于jvm自动内存管理的范围是堆内存,而直接内存是在堆内存之外(其实是内存映射文件,自行去理解虚拟内存空间的相关概念),所以直接内存的分配和回收都是有Unsafe类去操作,java在申请一块直接内存之后,会在堆内存分配一个对象保存这个堆外内存的引用,这个对象被垃圾收集器管理,一旦这个对象被回收,相应的用户线程会收到通知并对直接内存进行清理工作。
  • 相关阅读:
    ezjailserver备份和恢复方法
    三种方式上传文件-Java
    将EBS设为首页worklist删除误报
    软软测试总结检查
    C++包括头文件&lt;&gt;和&quot;&quot;差额
    web报告工具FineReport在使用方法和解决方案常见错误遇到(一)
    WEB流程设计器 = jQuery + jsPlumb + Bootstrap
    SuperMap/PlottingSymbol
    基于easyui开发Web版Activiti流程定制器详解(六)——Draw2d的扩展(三)
    基于easyui开发Web版Activiti流程定制器详解(六)——Draw2d详解(二)
  • 原文地址:https://www.cnblogs.com/GY8023/p/13596937.html
Copyright © 2020-2023  润新知