前言:
在学习spring-boot的过程中,碰到了2个用户同时登录,同时修改对应的数据库的问题,处理不当可能引发脏读等不良后果,导致系统错误,于是引入ThreadLocal对应处理(对登录实例中是使用)
过程:
第一步:导入工具类
public class ThreadLocalUtil {
//提供ThreadLocal对象,
private static final ThreadLocal THREAD_LOCAL = new ThreadLocal();
//根据键获取值
public static <T> T get(){
return (T) THREAD_LOCAL.get();
}
//存储键值对
public static void set(Object value){
THREAD_LOCAL.set(value);
}
//清除ThreadLocal 防止内存泄漏
public static void remove(){
THREAD_LOCAL.remove();
}
}
以上代码提供了TreadLocal对象并且定义了get和set方法,用set为TreadLocal赋值,每一个登录用户都有对应的TreadLocal,使其不产生数据报错等
第二步:在需要的地方为TreadLocal赋值
Map<String, Object> claims = JwtUtil.parseToken(token);
//把业务数据存储到ThreadLocal中,为之后复用便利
ThreadLocalUtil.set(claims);
由于前段页面需要数据为json格式,使用Map集合便捷传参使用。后续使用中直接调用即可
第三步:调用
Map<String,Object> map = ThreadLocalUtil.get();
Integer userId = (Integer) map.get("id");
获取id
实践完成后,我查询了TreadLocal的理论,理论如下:
理论:
从字面意思上看,ThreadLocal可以解释成线程的局部变量,也就是说一个ThreadLocal的变量只有当前自身线程可以访问,别的线程都访问不了,那么自然就避免了线程竞争。
因此,ThreadLocal提供了一种与众不同的线程安全方式,它不是在发生线程冲突时想办法解决冲突,而是彻底的避免了冲突的发生。
ThreadLocal.ThreadLocalMap是一个比较特殊的Map,它的每个Entry的key都是一个弱引用:
这样设计的好处是,如果这个变量不再被其他对象使用时,可以自动回收这个ThreadLocal对象,避免可能的内存泄露。