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

相关推荐
寻星探路9 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
曹牧11 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
爬山算法12 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty72512 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎12 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
李少兄12 小时前
在 IntelliJ IDEA 中修改 Git 远程仓库地址
java·git·intellij-idea
忆~遂愿12 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能
小韩学长yyds12 小时前
Java序列化避坑指南:明确这4种场景,再也不盲目实现Serializable
java·序列化
仟濹12 小时前
【Java基础】多态 | 打卡day2
java·开发语言