ThreadLocal 快速入门

ThreadLocal 快速入门

ThreadLocal 是 Java 中的一个类,用于创建线程局部变量。线程局部变量是一种特殊的变量,每个线程都有自己的副本,互相之间不会相互影响。这在多线程环境中非常有用,可以避免线程间共享变量导致的并发问题。

  1. 定义与作用 : ThreadLocal 是 Java 中的一个类,用于创建线程局部变量。它提供了一种在每个线程中都创建独立副本的机制。这意味着每个线程都可以访问自己的变量副本,而不会影响其他线程。
  2. 使用场景 :
    • 线程安全性 :在多线程环境中,使用 ThreadLocal 可以避免共享变量的竞争条件,提高程序的线程安全性。
    • 上下文传递 :有些情况下,需要在同一个线程的不同方法之间传递数据,但又不希望使用方法参数或全局变量。这时候可以使用 ThreadLocal 来存储线程相关的数据,方便在整个线程的执行过程中访问。例如:项目中想要获取登录人的id,就可以使用ThreadLocal
    • 线程封闭:有些对象是线程不安全的,但是如果每个线程都有自己的副本,就可以避免共享对象导致的线程安全问题。
  3. 使用方式 :
    • 创建 ThreadLocal 对象:可以直接实例化 ThreadLocal 类,也可以通过 ThreadLocal 的静态方法 withInitial(Supplier<? extends S> supplier) 来创建并初始化 ThreadLocal 实例。
    • 设置值:通过 set(T value) 方法设置当前线程的变量副本的值。
    • 获取值:通过 get() 方法获取当前线程的变量副本的值。
    • 移除值:通过 remove() 方法移除当前线程的变量副本。
  4. 内存泄漏问题 : 使用 ThreadLocal 时需要注意内存泄漏的问题。因为 ThreadLocal 是与线程绑定的,如果线程不结束,ThreadLocal 中的值可能无法释放,导致内存泄漏。为了避免这个问题,最好在使用完 ThreadLocal 后调用 remove() 方法将其值移除。
  5. 线程池中的使用 : 在使用线程池的情况下,需要特别小心 ThreadLocal 的使用。因为线程池中的线程是可以被复用的,如果 ThreadLocal 的值没有在使用完后及时清理,可能会影响到其他任务的执行。通常建议在使用完 ThreadLocal 后手动调用 remove() 方法清理。

ThreadLocal常用方法:

A. public void set(T value) : 设置当前线程的线程局部变量的值

B. public T get() : 返回当前线程所对应的线程局部变量的值

C. public void remove() : 删除当前线程所对应的线程局部变量的值

我们可以在LoginCheckFilter的doFilter方法中获取当前登录用户id,并调用ThreadLocal的set方法来设置当前线程的线程局部变量的值(用户id),然后在MyMetaObjectHandler的updateFill方法中调用ThreadLocal的get方法来获得当前线程所对应的线程局部变量的值(用户id)。 如果在后续的操作中, 我们需要在Controller / Service中要使用当前登录用户的ID, 可以直接从ThreadLocal直接获取。

案例:

项目中想要获取登录人的id

1).BaseContext工具类

java 复制代码
/**
 * 基于ThreadLocal封装工具类,用户保存和获取当前登录用户id
 */
public class BaseContext {
    private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
    /**
     * 设置值
     * @param id
     */
    public static void setCurrentId(Long id){
        threadLocal.set(id);
    }
    /**
     * 获取值
     * @return
     */
    public static Long getCurrentId(){
        return threadLocal.get();
    }
}

2).LoginCheckFilter中存放当前登录用户到ThreadLocal

在doFilter方法中, 判定用户是否登录, 如果用户登录, 在放行之前, 获取HttpSession中的登录用户信息, 调用BaseContext的setCurrentId方法将当前登录用户ID存入ThreadLocal。

java 复制代码
Long empId = (Long) request.getSession().getAttribute("employee");
BaseContext.setCurrentId(empId);

3). MyMetaObjectHandler中从ThreadLocal中获取

将之前在代码中固定的当前登录用户1, 修改为动态调用BaseContext中的getCurrentId方法获取当前登录用户ID

相关推荐
小蒜学长1 小时前
微信小程序-高校自习室管理系统(代码+数据库+LW)
java·spring boot·后端·微信小程序·自习室管理
鸥梨菌Honevid2 小时前
UVM 中 REQ 和 RSP 类型详解:从通信模型到 item_done 与 put_response
java·前端·servlet
瑞克-桑切斯2 小时前
真实企业场景 运维安全与管理
java·网络·github
老板一杯拿铁2 小时前
Java 八股文面试详解:从基础到进阶的全面梳理
java·面试
const_qiu2 小时前
第 2.5 章 2.5.4-2.5.5:JWT 双 Token 与声明式权限守卫
java·人工智能
bug菌2 小时前
一个周末就想把短链服务推到 10 万 QPS,真能靠加 Redis 做到吗?
java·redis·go
撸串-研究生2 小时前
springboot福利院管理系统73979
java·spring boot·后端·福利院管理系统
不得了zz3 小时前
04-Spring AI Alibaba ReactAgent 生产级实践:工具调用、结构化输出、HITL 与上下文管理
java·ai编程·springaialibaba
猿究院_夏燊3 小时前
SpringMVC 到底是怎么干活的?
java·网络·职场和发展
鶴哥只手遮天3 小时前
Spring Framework 7.0.9 深度剖析-05-配置元数据解析:XML、注解与 JavaConfig
java·后端·开源