什么是ThreadLocal
ThreadLocal是一个线程级别变量,每个线程都有一个 ThreadLocal 就是每个线程都拥有了自己独立的一个变量,竞态条件被彻底消除了,在并发模式下是绝对安全的变量。
可以通过
ThreadLocal<T> value = new ThreadLocal<T>()
来使用。
会自动在每一个线程上创建一个 泛型实例,实例之间彼此独立,互不影响,可以用 ThreadLocal 存储一些参数,以便在线程中多个方法中使用,用以代替方法传参的做法。
ThreadLocal 使用场景
现在假设有两个用户同时访问你的资源,通常情况下会将两个用户的信息存进 redis 方便后续获取,一般不再从数据库进行调用,因为高并发的情况下数据库不能承担大量的请求。但是由于redis里面会存每一个用户的信息,在取信息的时候并不知道是谁的,就会导致取错的情况。
于是引入ThreadLocal ,它将每个用户的信息在请求该资源时便存进ThreadLocal ,由于ThreadLocal 的独立性,每个用户都有自己的ThreadLocal 变量,下次需要信息就可以直接从ThreadLocal 中获取。
ThreadLocal使用实例
private static ThreadLocal<Map<String, Object>> TL
= ThreadLocal.withInitial(HashMap::new);
如上述代码所示,ThreadLocal 通常作为工具类使用,通过 ThreadLocal 的 withInitial() 方法,我们可以指定一个初始值的提供者。在这里,初始值提供者是一个 lambda 表达式,它创建并返回一个新的 HashMap 对象。因此,每个线程在访问 TL 变量时,都会获得一个独立的 HashMap实例。
public static void set(String key, Object value) {
Map<String, Object> map = TL.get();
map.put(key, value);
}
首先,通过调用 TL.get() 方法获取当前线程的 ThreadLocal 变量的值,该值是一个 Map<String, Object> 对象。TL 是之前定义的ThreadLocal变量。然后,通过获取到的 Map 对象,使用 put() 方法将指定的键值对存储到 Map 中。传入的参数 key 是键的名称,value 是要存储的值。 这段代码的作用是将键值对存储到当前线程的 ThreadLocal 变量中。由于 ThreadLocal 提供了线程局部变量的功能,每个线程都有自己独立的存储空间,因此存储在 ThreadLocal 中的数据对其他线程是不可见的,从而实现了线程之间的数据隔离。
整个工具类如下:
public class ThreadLocalUtil {
private static ThreadLocal<Map<String, Object>> TL = ThreadLocal.withInitial(HashMap::new);
public static void set(String key, Object value) {
Map<String, Object> map = TL.get();
map.put(key, value);
}
public static Object get(String key) {
Map<String, Object> map = TL.get();
return map.get(key);
}
public static void remove(String key) {
Map<String, Object> map = TL.get();
map.remove(key);
}
public static void clear() {
TL.remove();
}
}