ThreadLocal是Java中一个线程级别的变量,它可以让每个线程都拥有自己单独的变量副本,实现了线程间数据的隔离。ThreadLocal提供了一种创建线程局部变量的方式,每个线程都可以独立地改变自己的副本,而不会影响其他线程的副本。ThreadLocal通常用于在多线程环境下保存线程私有的数据,例如用户身份信息、数据库连接、Session对象等。通过ThreadLocal可以避免线程之间的数据共享问题,提高程序的性能和安全性。
ThreadLocal的作用如下:
提供线程局部变量:ThreadLocal提供了一种创建线程局部变量的方式,每个线程都可以独立地改变自己的副本,而不会影响其他线程的副本。
隔离线程之间的数据:ThreadLocal可以隔离线程之间的数据,每个线程都可以有自己的副本,这样就避免了线程之间的数据共享问题。
提高程序性能:ThreadLocal可以提高程序的性能,因为每个线程都可以直接访问自己的副本,不必竞争共享变量,避免了线程间的锁竞争问题。
管理共享变量的访问:ThreadLocal可以管理共享变量的访问,每个线程都可以通过ThreadLocal对象访问共享变量,而不必担心线程安全问题。ThreadLocal的作用就是提供一种线程安全的方式,管理共享变量的访问,隔离线程之间的数据,提高程序性能。
1、创建ThreadLocal对象
private static final ThreadLocal USER_INFO_LOCAL = new ThreadLocal();
2、设置值
public static void setLoginUserVO(UserInfo loginUserVO) {USER_INFO_LOCAL.set(loginUserVO);
}
3、获取值
public static UserInfo getLoginUserVO() {return (UserInfo)USER_INFO_LOCAL.get();
}
4、删除数据
public static void clear() {USER_INFO_LOCAL.remove();
}
需要注意,ThreadLocal一般用于解决多线程环境下共享变量的问题,但也容易引发内存泄露问题,因此在使用完后需要及时清理ThreadLocal中的数据。
// ThreadLocal实例的唯一标识符,是通过nextHashCode()方法生成的,它保证了ThreadLocal实例之间的唯一性和线程安全性。
private final int threadLocalHashCode = nextHashCode();// 是ThreadLocal类中nextHashCode()方法中生成哈希值的一个增量,它是一个常数,用于降低哈希冲突,保证哈希表的性能和线程安全性。
private static final int HASH_INCREMENT = 0x61c88647;
// nextHashCode是一个AtomicInteger类型的变量,用于生成ThreadLocal实例的哈希码
private static AtomicInteger nextHashCode = new AtomicInteger();
// 无参构造函数
public ThreadLocal() {
}
ThreadLocal类的构造函数不接受任何参数,主要是每个ThreadLocal实例都是与特定线程相关,而不是特定的数据类型相关联的。因此,每个ThreadLocal实例可以存储任何类型的值,而不需要指定类型。这也是ThreadLocal类的一个重要特点,它提供了一种通用的、线程安全的机制来存储每个线程的数据,避免了多线程环境中共享变量的问题。
因此,public ThreadLocal()的含义是ThreadLocal类的构造方法,用于创建一个新的ThreadLocal实例,并初始化为默认值null。在使用ThreadLocal实例时,需要使用set方法为其设置一个初始值。
用于为当前线程中ThreadLocal对象设置值。
获取当前线程;
根据当前线程获取对应的ThreadLocalMap对象。
如果ThreadLocalMap对象存在,则使用set方法将ThreadLocal对象和值保存到ThreadLocalMap对象中。
如果ThreadLocalMap对象不存在,说明当前线程还没有ThreadLocalMap对象,此时需要使用createMap方法为其创建一个ThreadLocalMap对象,并将ThreadLocal对象和值保存到其中。
// 为当前线程中ThreadLocal对象设置值
public void set(T value) {// 获取当前线程Thread t = Thread.currentThread();// 根据当前线程获取对应的ThreadLocalMap对象。ThreadLocalMap map = getMap(t);// 如果ThreadLocalMap对象存在,使用set方法将ThreadLocal对象和值保存到ThreadLocalMap对象中。if (map != null)map.set(this, value);else// 如果ThreadLocalMap对象不存在,使用createMap方法为其创建一个ThreadLocalMap对象,并将ThreadLocal对象和值保存到其中。createMap(t, value);
}
用于获取当前线程中ThreadLocal对象对应的值。
获取当前线程;
根据当前线程获取对应的ThreadLocalMap对象。
如果ThreadLocalMap对象存在,则从中获取ThreadLocal对象对应的Entry对象,
如果Entry对象存在,则返回其值,否则返回null。
如果ThreadLocalMap对象不存在,说明当前线程还没有ThreadLocalMap对象,此时需要使用setInitialValue方法来为其设置一个初始值,并返回该值。
// 如果没有获取到数据,则会初始一个数据,将线程当作key,null 当作value 放入ThreadLocalMap中
public T get() {// 获取当前线程。Thread t = Thread.currentThread();// 根据当前线程获取对应的ThreadLocalMap对象ThreadLocalMap map = getMap(t);// 如果ThreadLocalMap对象存在if (map != null) {// 从中获取ThreadLocal对象对应的Entry对象。ThreadLocalMap.Entry e = map.getEntry(this);// 如果Entry对象存在,则返回其值if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}// 如果ThreadLocalMap对象不存在,说明当前线程还没有ThreadLocalMap对象,此时需要使用setInitialValue方法来为其设置一个初始值,并返回该值。return setInitialValue();
}
用于为当前线程中ThreadLocal对象设置一个初始值。
调用initialValue方法获取初始值;
获取当前线程;
根据当前线程获取对应的ThreadLocalMap对象。
如果ThreadLocalMap对象存在,则使用set方法将ThreadLocal对象和初始值保存到ThreadLocalMap对象中。
如果ThreadLocalMap对象不存在,说明当前线程还没有ThreadLocalMap对象,此时需要使用createMap方法为其创建一个ThreadLocalMap对象,并将ThreadLocal对象和初始值保存到其中。
最后,返回设置的初始值。
// 初始值,key:当前线程,value:null
private T setInitialValue() {// 调用initialValue方法获取初始值;实际上是null T value = initialValue();// 获取当前线程Thread t = Thread.currentThread();// 根据当前线程获取对应的ThreadLocalMap对象ThreadLocalMap map = getMap(t);// 如果ThreadLocalMap对象存在,则使用set方法将ThreadLocal对象和初始值保存到ThreadLocalMap对象中if (map != null)map.set(this, value);else// 如果ThreadLocalMap对象不存在,说明当前线程还没有ThreadLocalMap对象,此时需要使用createMap方法为其创建一个ThreadLocalMap对象,并将ThreadLocal对象和初始值保存到其中。createMap(t, value);// 返回设置的初始值return value;
}
用于清除当前线程中ThreadLocal对象的值。
获取当前线程,然后根据当前线程获取对应的ThreadLocalMap对象。
如果ThreadLocalMap对象存在,则使用remove方法将ThreadLocal对象从ThreadLocalMap对象中移除。
如果ThreadLocalMap对象不存在,则说明当前线程中没有该ThreadLocal对象的值,因此无需进行任何操作。
public void remove() {// 获取当前线程,然后根据当前线程获取对应的ThreadLocalMap对象ThreadLocalMap m = getMap(Thread.currentThread());// 如果ThreadLocalMap对象存在if (m != null)// 则使用remove方法将ThreadLocal对象从ThreadLocalMap对象中移除。m.remove(this);
}