Java并发 --- ThreadLocal简述

作者: _code_x | 来源:发表于2021-07-09 22:34 被阅读0次

    ThreadLocal对象可以提供线程局部变量,每个线程Thread拥有一份自己的副本变量,多个线程互不干扰。

    ThreadLocal的数据结构

    • 每一个 Thread 对象均含有一个 ThreadLocalMap 类型的成员变量 threadLocals ,它存储本线程中所有ThreadLocal对象及其对应的值
    • ThreadLocalMap有自己的独立实现,可以简单地将它的key视作ThreadLocal,value为代码中放入的值(实际上key并不是ThreadLocal本身,而是它的一个弱引用)。ThreadLocalMap有点类似HashMap的结构,只是HashMap是由数组+链表实现的,而ThreadLocalMap中并没有链表结构。
    • 每个线程在往ThreadLocal里放值的时候,都会往自己的ThreadLocalMap里存,读也是以ThreadLocal作为引用,在自己的map里找对应的key,从而实现了线程隔离。
    • 我们还要注意Entry, 它的key是ThreadLocal<?> k ,继承自WeakReference, 也就是我们常说的弱引用类型。一个 Entry 由 ThreadLocal 对象(key)和 Object 构成。

    Java四种引用类型

    • 强引用:我们常常new出来的对象就是强引用类型(或者反射创建的对象),只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足的时候
    • 软引用:使用SoftReference修饰的对象被称为软引用,软引用指向的对象在内存要溢出的时候被回收
    • 弱引用:使用WeakReference修饰的对象被称为弱引用,只要发生垃圾回收,若这个对象只被弱引用指向,那么就会被回收
    • 虚引用:虚引用是最弱的引用,在 Java 中使用 PhantomReference 进行定义。虚引用中唯一的作用就是用队列接收对象即将死亡的通知

    ThreadLocal的set方法分析

    • set方法实际是set到当前线程(先创建)的map中,key就是ThreadLocal对象,value要存储值
    • 将key指向ThreadLocal的引用改为弱引用(如果是强引用ThreadLocal对象不能被回收,内存泄露),可以回收,但是key( == null)访问不到value了(内存泄露),一定要调用remove()掉!

    ps:为什么不等到当前线程自己销毁?(1)可能长时间不关闭(2)可能是线程池的线程,用完归还

    ThreadLocal应用场景

    • 在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。可以看成属于线程的一个全局变量。设置在线程本地,如果设置成static多线程存在安全问题
    • Spring框架在事务开始时会给当前线程绑定一个Jdbc Connection,在整个事务过程都是使用该线程绑定的connection来执行数据库操作,实现了事务的隔离性。Spring框架里面就是用的ThreadLocal来实现这种隔离。
    • 即@Transational,首先保证在拿到的是同一个连接,才能保证在同一个事务中,解决方案:把connection放到ThreadLocal,任何被事务所管理的方法,用到connection去ThreadLocal取,而不是去连接池取,永远都是同一个connection。

    巨人的肩膀:

    https://juejin.im/post/5eacc1c75188256d976df748

    相关文章

      网友评论

        本文标题:Java并发 --- ThreadLocal简述

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