ThreadLocal原理简述(简单易懂)

211 阅读2分钟

ThreadLocal简介:

ThreadLocal 类是用来提供线程内部的局部变量,即线程本地变量。这种变量在多线程环境下访问(通过get和set方法访问)时能够保证各个线程的变量相对独立于其他线程内的变量,不同线程之间不会相互干扰,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或组件之间一些公共变量传递的复杂度。

ThreadLocal使用效果:

image.png

涉及到的类以及之间的关系:

image.png 1.ThreadLocal类: 包含设置值和获取值的方法:

public void set(T value) {
    Thread t = Thread.currentThread();
    // 获取当前线程的ThreadLocalMap对象
    ThreadLocalMap map = this.getMap(t);
    // 将变量值存放在ThreadLocalMap对象中,key为ThreadLocal对象的引用,value为变量值
    if (map != null) {
        map.set(this, value);
    } else {
        this.createMap(t, value);
    }

}
public T get() {
    Thread t = Thread.currentThread();
     // 获取当前线程的ThreadLocalMap对象
    ThreadLocalMap map = this.getMap(t);
    // 从ThreadLocalMap对象中取出ThreadLocal对象对应的值
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            T result = e.value;
            return result;
        }
    }
    return this.setInitialValue();
}

2.ThreadLocalMap
ThreadLocal类的静态内部类,是Thread类中的成员变量。 image.png ThreadLocalMap中的Entry数组table,用来实际存放ThreadLocal对象以及对应的变量值。 image.png image.png

实现原理:

  1. 每个线程的本地变量不是存放在ThreadLocal里面,而是存放在调用线程的threadLocals变量(ThreadLocalMap对象)里,就是说ThreadLocal类型的本地变量存放在具体的线程内存空间中;
  2. ThreadLocal就是个工具壳,它通过set方法把value值放入调用线程的threadLocals(ThreadLcoalMap对象)里面,当线程调用它的get方法时,再从线程的threadLocals里面将其拿出来使用;

实现原理总结:

ThreadLocal类型的成员变量的变量值是通过ThreadLocal对象的set和get方法在当前线程中进行存放和获取的,每个线程都有一个变量副本,线程间对各自变量副本的操作是独立的不会相互影响。

补充知识:

ThreadLocalMap的key为什么是弱引用?

  1. 避免内存泄漏如果ThreadLocalMap的key是强引用,当线程的ThreadLocal变量不再使用时(即将ThreadLocal变量设为null),由于线程对象仍然持有ThreadLocalMap的强引用,而ThreadLocalMap又持有ThreadLocal实例的强引用,这会导致即使没有其他地方引用ThreadLocal实例,垃圾回收器也无法回收它,从而引起内存泄漏
  2. 便于垃圾回收通过使用弱引用作为key,当线程局部变量不再被使用且没有其他强引用指向它时,垃圾回收器可以在下一次回收周期中回收ThreadLocal实例及其关联的Entry,从而释放内存,防止内存泄漏

因此,将ThreadLocalMap的key设计为弱引用是一种内存管理上的策略,旨在提供自动清理不再使用的ThreadLocal实例的能力,确保了更好的内存管理