• ThreadLocal的原理和使用场景。


        ThreadLocal的原理和使用场景

        每一个Thread对象,均含有一个ThreadLocalMap类型的成员变量,threadLocals,它存储本线程中所有的ThreadLocal对象及其对应值。

        ThreadLocalMap对象由一个Entry对象构成。

        Entry继承自weakReference(<threadLocal>),一个Entry由ThreadLocal对象和Object构成。由此可见,Entry的key是ThreadLocal对象,并且是一个弱引用,当没指向key的强引用后,该key就会被垃圾收集器回收。

        当执行set方法时,ThreadLocal首先会获取当前线程对象,然后获取当前线程的ThreadLocalMap对象,在以当前ThreadLocal对象为key,将值存储到ThreadLocalMap中。

        get方法执行过程类似。ThreadLocal首先会获取当前线程的对象,然后获取当前线程的ThreadLocalMap对象,再以当前的ThreadLocal对象为key,获取对应的value。

        由于每一条线程均含有各自私有的ThreadLocalMap容器,这些容器相互独立,互不影响,因此不会存在线程安全问题,从而也不用使用同步机制来保证多条访问容器的互斥性。    

      

        ThreadLocal使用场景:

        1 、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。  譬如一个User对象,要从Controller传递到service层,在到dao层,可以直接使用ThreadLocal修饰,跨层传递。

        2 、线程间数据隔离。

        3 、 进行事务操作,用来存储线程事务信息。

        4 、 数据库连接,session会话管理。

      

        Spring框架在事务开始时会给当前线程绑定一个jdbcConnection,在整个事务过程都是使用该线程绑定的Connection来执行数据库操作,实现事务隔离性,Spring框架里面用的就是ThreadLocal进行隔离。

        

        

        

        ThreadLocal内存泄漏的原因,如何避免?

        什么是内存泄漏?

        不会被使用的对象或者变量占用的内存不能被回收,就收内存泄漏。

        内存泄漏是程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏危害可以忽略,但内存泄漏堆积后果很严重,无论多少内存都会被沾光。

        强引用:使用最普通的引用(new),一个对象具有强引用,不会被垃圾回收器回收。当内存空间不足,java虚拟机会抛出OutOfMemoryError错误,使程序异常终止,也不会回收这种对象。

        如果想取消强引用和某个对象之间的关联,可以显式的将引用赋值为null,这样可以使jvm在合适的时间就会回收该对象。

        

        弱引用: jvm进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用java.lang.ref.WeakReference类来表示,可以在缓存中使用弱引用。

        

        ThreadLocal实现的原理,每一个Thread维护一个ThreadLocalMap,key为使用弱引用的ThreadLocal实例,value为线程变量的副本。

        

        

        如图:虚线代表弱引用,实线代表强引用。

        ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal不存在外部强引用时,key(ThreadLocal)势必会被回收,这样就会导致ThreadLocalMap中的key为null,而value中还存在着强引用。

        只有Thread线程退出以后,value的强引用链条才会断掉。但如果当前线程迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链(红色链条)。

        

        如果key使用强引用

        当 ThreadlocalMap的key为强引用,回收ThreadLocal时,因为ThreadLocalMap还使用ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,导致Entry内存泄漏。

        

        实际key使用弱引用

        当ThreadLocalMap的key为弱引用,回收ThreadLocal时,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收,当key为null时,在下一次ThreadLocal调用set,get,remove时,就会被清除回收value中的值。

        因此,ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期和ThreadLocal的一样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用。

        

        ThreadLocal的正确使用方法:

        1)每次使用完ThreadLocal都调用他的remove方法清除数据。

        2)将ThreadLocal变量定义为private static ,这样就能一直存在ThreadLocal的强引用,也就能保证任何时候都能通过ThreadLocal的弱引用访问到Entry的值,进而清除掉。

      

         

        

  • 相关阅读:
    如何调用ActiveX网页中的JavaScript函数
    VC++开发的ActiveX如何加入安全机制,避免IE中提示“在此页上的ActiveX控件和本页上的其他部分的交互可能不安全,你想允许这种交互吗?”
    ActiveX多线程回调JavaScript
    JavaScript脚本如何访问VC++开发的ActiveX中的方法
    ActiveX异步回调JavaScript
    com/atl套间编程中如何实现定时invoke容器中的方法
    VC++开发的ActiveX如何通过JavaScript脚本和EOS应用交互
    thread wrapper
    最新Mysql中文帮助
    如何避免重复的http请求
  • 原文地址:https://www.cnblogs.com/hrlizhi/p/14643180.html
Copyright © 2020-2023  润新知