美文网首页java全栈
ThreadLocal保存用户登录信息(防止内存泄露)

ThreadLocal保存用户登录信息(防止内存泄露)

作者: 小名源治 | 来源:发表于2022-08-06 14:49 被阅读0次

    为什么会出现内存泄露

    ThreadLocal线程实现是一个Map(每一个Thread维护一个ThreadLocalMap),Map中有一个Key、一个value。其中的Key指向的就是我们new出来的ThreadLocal线程,value就是我们保存的数据。其中key指向ThreadLocal是弱引用,而value指向我们保存的数据是强引用。线程回收的时候会将弱引用的东西回收,保留强引用。
    ThreadLocal所在线程进行一次垃圾回收,那么Key就会被GC回收,这样就会导致ThreadLocalMap中key为null,而value还存在强引用。这样我们的Value就会永远存在我们的内存中,无法被删除(如果有大量的类似情况就会造成内存泄露)。
    解决办法:在GC之前手动删除整个ThreadLocalMap。

    强引用:使用最普遍的引用,一个对象具有强引用,不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError(内存溢出)错误,使程序异常终止,也不回收这种对象。
    弱引用:JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。

    如果想取消强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样可以使JVM在合适的时间就会回收该对象。

    下面是代码实现

    1.前提

    JWT登录验证通过后保存


    image.png

    2.新建一个UserThreadLocal类来保存用户信息,其中实现put() get() remove()方法,其中初始化一个静态常量ThreadLocal

    /**
     * 保存用户信息
     * 线程变量隔离,每个线程都会绑定一个ThreadLocal,这样就不会起冲突
     */
    public class UserThreadLocal {
    
        private UserThreadLocal() {
        }
    
        private static final ThreadLocal<SysUser> LOCAL = new ThreadLocal<>();
    
        public static void put(SysUser sysUser) {
            LOCAL.set(sysUser);
        }
    
        public static SysUser get() {
            return LOCAL.get();
        }
    
        public static void remove() {
            LOCAL.remove();
        }
    }
    
    

    3.调用put方法,保存用户信息

    //将用户信息放入到本地保存
    UserThreadLocal.put(user);
    

    4.最后在afterCompletion方法中,将保存的信息删除(防止内存泄露)

    afterCompletion方法:来自于HandlerInterceptor父类中的重写,在所有方法都执行完毕后才会执行此方法。(一般用于收尾工作)

        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            //最后执行结束需要将ThreadLocal中的信息删除  不删除会有内存泄露的风险
            UserThreadLocal.remove();
        }
    

    相关文章

      网友评论

        本文标题:ThreadLocal保存用户登录信息(防止内存泄露)

        本文链接:https://www.haomeiwen.com/subject/prfvwrtx.html