ThreadLocal简介:
ThreadLocal 类是用来提供线程内部的局部变量,即线程本地变量。这种变量在多线程环境下访问(通过get和set方法访问)时能够保证各个线程的变量相对独立于其他线程内的变量,不同线程之间不会相互干扰,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或组件之间一些公共变量传递的复杂度。
ThreadLocal使用效果:
涉及到的类以及之间的关系:
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类中的成员变量。
ThreadLocalMap中的Entry数组table,用来实际存放ThreadLocal对象以及对应的变量值。
实现原理:
- 每个线程的本地变量不是存放在ThreadLocal里面,而是存放在调用线程的threadLocals变量(ThreadLocalMap对象)里,就是说ThreadLocal类型的本地变量存放在具体的线程内存空间中;
- ThreadLocal就是个工具壳,它通过set方法把value值放入调用线程的threadLocals(ThreadLcoalMap对象)里面,当线程调用它的get方法时,再从线程的threadLocals里面将其拿出来使用;
实现原理总结:
ThreadLocal类型的成员变量的变量值是通过ThreadLocal对象的set和get方法在当前线程中进行存放和获取的,每个线程都有一个变量副本,线程间对各自变量副本的操作是独立的不会相互影响。
补充知识:
ThreadLocalMap的key为什么是弱引用?
- 避免内存泄漏:如果ThreadLocalMap的key是强引用,当线程的ThreadLocal变量不再使用时(即将ThreadLocal变量设为null),由于线程对象仍然持有ThreadLocalMap的强引用,而ThreadLocalMap又持有ThreadLocal实例的强引用,这会导致即使没有其他地方引用ThreadLocal实例,垃圾回收器也无法回收它,从而引起内存泄漏。
- 便于垃圾回收:通过使用弱引用作为key,当线程局部变量不再被使用且没有其他强引用指向它时,垃圾回收器可以在下一次回收周期中回收ThreadLocal实例及其关联的Entry,从而释放内存,防止内存泄漏。
因此,将ThreadLocalMap的key设计为弱引用是一种内存管理上的策略,旨在提供自动清理不再使用的ThreadLocal实例的能力,确保了更好的内存管理。