一、简介
ThreadLocal
叫做线程变量,意思是ThreadLocal
中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal
为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意:
- 因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这是也是 ThreadLocal 命名的由来。
- 既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题。
ThreadLocal 提供了线程本地的实例。它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。
总的来说,ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景
下图可以增强理解:
二、获取过程
通过jwt认证的流程,我们可以从拦截器中获取到 用户id
在登录的时候,存用户的id到 claims这个map中;
从拦截器中我们可以取到 id;那么我们先通过拦截器,将id 存储到这个线程中;
通过前后端联调我们可以发现,前端的每一次请求,对应的是一个单独的线程;
也就是说,我们可以通过localthread来获取到一次请求中的数据;
ThreadLocal为每一个线程提供一份单独的存储空间,具有线程隔离效果(其他线程访问不到)。
ThreadLocal 常用方法
public void set(T value) //设置当前线程的线程局部变量的值
public T get() //返回当前线程所对应的线程局部变量的值
public void remove() //移除当前线程的线程局部变量
在使用的时候我们一般会封装成工具来调用;
public class BaseContext {
public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
public static void setCurrentId(Long id) {
threadLocal.set(id);
}
public static Long getCurrentId() {
return threadLocal.get();
}
public static void removeCurrentId() {
threadLocal.remove();
}
}
那么在 service中 我们只需要 BaseContext.get 就可以了;
//设置当前记录创建人id和修改人id
employee.setCreateUser(BaseContext.getCurrentId());
三、总结
ThreadLocal一般封装成工具类
在通过JWT验证登录时,可以通过拦截器来获取到 token令牌中的参数,再通过ThreadLocal封装的工具类获取到该数据,就可以在方法中调用,获取到数据;