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

相关推荐
追风林2 分钟前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
芒果披萨17 分钟前
El表达式和JSTL
java·el
duration~1 小时前
Maven随笔
java·maven
zmgst1 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD1 小时前
前后端分离,Jackson,Long精度丢失
java
blammmp2 小时前
Java:数据结构-枚举
java·开发语言·数据结构
暗黑起源喵2 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong2 小时前
Java反射
java·开发语言·反射
九圣残炎2 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
wclass-zhengge2 小时前
Netty篇(入门编程)
java·linux·服务器