ThreadLocal原理与使用
文章目录
- 实现原理
- ThreadLocal的存值操作
- ThreadLocal的取值操作
- 使用场景
ThreadLocal是Java中的一个线程本地存储类,它可以用于将某个对象绑定到当前线程上。这样,在同一个线程中不同方法都可以访问到这个对象,而不需要将对象作为参数传递或者使用全局变量。
实现原理
ThreadLocal内部使用了一个ThreadLocalMap类来保存每个线程的值。ThreadLocalMap是一个使用线性探测法解决哈希冲突的哈希表,它的键值是ThreadLocal对象,值是对应线程中保存的对象。
当使用ThreadLocal.set方法设置一个值时,ThreadLocal首先获取当前线程,然后获取当前线程对应的ThreadLocalMap对象。ThreadLocalMap的getEntry方法使用ThreadLocal对象作为参数,返回当前线程中关联的Entry对象。如果Entry不存在,ThreadLocalMap就会使用ThreadLocal对象创建一个新的Entry并放到当前线程的ThreadLocalMap中。然后将需要保存的对象保存到Entry中。
当使用ThreadLocal.get方法获取值时,ThreadLocal还是会获取当前线程和对应的ThreadLocalMap对象,然后使用ThreadLocal对象作为参数调用ThreadLocalMap中的getEntry方法获取Entry。如果Entry不存在,ThreadLocalMap会使用ThreadLocal对象创建一个新的Entry并放到当前线程的ThreadLocalMap中。然后将新创建的Entry返回,Entry的getValue方法就可以返回之前保存的对象了。
ThreadLocal的存值操作
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
ThreadLocal的取值操作
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
使用场景
ThreadLocal通常用于下列情况:
- 将一个普通变量保存到ThreadLocal中,使其在当前线程中随时可用,从而避免多次传参的麻烦。
- 将有状态的组件保存到ThreadLocal中,使得它们在第二次使用时可以避免重复初始化,从而提高性能和效率。
- 实现线程安全的单例模式,通过ThreadLocal来保证每个线程内只有一个实例。
ThreadLocal使用需要注意的点
- 内存泄漏:ThreadLocalMap中的Entry对象是弱引用,只有在当前线程存活期内且该线程的ThreadLocalMap存在时,则Entry对象才不会被回收。如果ThreadLocal没有及时地被回收,会导致Entry对象无法回收,进而导致内存泄漏问题。
- 释放资源:使用ThreadLocal时需要手动调用remove方法来清除保存在线程中的对象,以免造成资源的浪费。
- 线程不安全:ThreadLocal只是用来保存本线程中的数据,因此在并发的情况下,每个线程都有自己的变量副本,因此不会发生线程安全的问题。但是,如果多个线程共用一个ThreadLocal,那么仍然会出现线程安全的问题。
还没有评论,来说两句吧...