ThreadLocal的使用以及原理
概要
ThreadLocal 是 java 提供的一个方便对象在本线程内不同方法中进行传递和获取的类。用它定义的变量,仅在本线程中可见和维护,不受其他线程的影响,与其他线程相互隔离。
一、ThreadLocal能解决什么问题?
当涉及一个对象需要在很多不同方法之间传递时,应该考虑使用 ThreadLocal 对象来简化代码。
1. 线程专属的本地变量
通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。如果想实现每一个线程都有自己的专属本地变量该如何解决呢?JDK 中自带的ThreadLocal类正是为了解决这样的问题。
2. 方法参数传递
虽然在本线程不同方法中使用变量,可以通过在方法中传入参数解决,但是当涉及多个方法甚至多个类时,为每个方法增加同样的参数将是一场噩梦,此时 ThreadLocal 就能很好地解决这个问题。它可以在本线程内任何一个地方赋值,在任何一个地方获取值,并且不用作为函数参数传入。
3. ThreadLocal 线程隔离
上面第2点提到的,静态成员变量也能解决。但是ThreadLocal 变量相比静态成员变量的一个优势就是,ThreadLocal 是线程隔离的,其值不会受另一个线程的影响,也不用考虑加锁或值被其他线程篡改的问题,而这些问题都是静态成员变量无法做到的。
二、ThreadLocal的使用场景
典型场景2: 每个线程内需要保存全局变量(例如在拦截器中获取用户信息),可以让不同方法直接使用,避免参数传递的麻烦。
三、ThreadLocal原理
ThreadLocal 能在每个线程间进行隔离,其主要是靠在每个 Thread 对象中维护一个 ThreadLocalMap 来实现的。因为是线程中的对象,所以对其他线程不可见,从而达到隔离的目的。之所以是Map结构,主要是因为一个线程中可能有多个 ThreadLocal 对象,这就需要一个集合来进行存储区分,而用 Map 可以更快地查找到相关的对象。
1. ThreadLocalMap
ThreadLocalMap 是 ThreadLocal 对象的一个静态内部类,内部维护一个 Entry 数组,实现类似 Map 的 get 和 put 等操作,为简单起见,可以将其看做是一个 Map,其中 key 是 ThreadLocal 实例,value 是 ThreadLocal 实例对象存储的值。
2. set
当调用 ThreadLocal 的 set 方法给变量设置值时,ThreadLocal 对象会先获取本线程的 ThreadLocalMap 对象,然后将当前的 ThreadLocal 对象及要设置值作为键值对放入 Map 中。
部分源码如下:
1 public void set(T value) { 2 // 获取当前请求的线程 3 Thread t = Thread.currentThread(); 4 5 // 取出Thread 类内部的 threadLocals 变量(哈希表结构) 6 ThreadLocalMap map = getMap(t); 7 if (map != null) 8 // this 指当前的 ThreadLocal 对象,将需要存储的值放入到这个哈希表中 9 map.set(this, value); 10 else 11 // key 不存在,则创建 map 并设置值 12 createMap(t, value); 13 } 14 15 ThreadLocalMap getMap(Thread t) { 16 // threadLocals 是 Thread 中的一个变量,因此是线程隔离的,不会受其他线程影响 17 // 其在 Thread 类中的定义如下:ThreadLocal.ThreadLocalMap threadLocals = null; 18 return t.threadLocals; 19 }
参考链接:
https://juejin.cn/post/6844904016288317448
标签:变量,Thread,ThreadLocalMap,对象,ThreadLocal,线程,使用,原理 From: https://www.cnblogs.com/hld123/p/18520904