扫码关注公众号
ThreadLocal是什么?讲讲你对ThreadLocal的理解
1隔离性:在多线程条件下ThreadLocal提供了线程间数据隔离的功能,从它的命名上也能知道这是属于一个线程的本地变量。也就是说,每个线程都会在ThreadLocal中保存一份该线程独有的数据,所以它是线程安全的。2生命周期:线程在存活并且ThreadLocal实例可被访问时,每个线程隐含持有一个线程局部变量副本,当线程生命周期结束时,ThreadLocal的实例的副本跟着线程一起消失,被GC垃圾回收(除非存在对这些副本的其他引用)
ThreadLocal有哪些使用场景?
1登录的用户信息:假如有两个用户A和B,他们分别进行登录,并且他们的每次请求都会带有自己的token,在请求到达controller之前(preHandle()中),每次都会被会被拦截器进行拦截,提取出当前token中的用户信息(比如userId),认证通过以后在service中就可以通过Contenxt类获取提取出来的用户信息。Context类可以使用ThreadLocal类型的对象(ThreadLocalUSER_ID=new…)进行存储2线程池:多个线程频繁访问时对conn对象的原子性造成影响,所以需要使用同步机制,但是使用严格的lock机制又会造成性能的下降。可以使用ThreadLocal为每个请求保持conn的副本,通过其隔离性较好的降低对象的同步问题和创建开销
ThreadLocal每次请求后被gc掉了,为什么还能请求到上一个用户信息?
1当使用ThreadLocal保存一个value时,会在ThreadLocalMap中的数组插入一个Entry对象,按理说key-value都应该以强引用保存在Entry对象中,但在ThreadLocalMap的实现中,key被保存到了弱引用对象中。这就导致了一个问题,ThreadLocal在没有外部强引用时,发生GC时会被回收,如果创建ThreadLocal的线程一直持续运行,那么这个Entry对象中的value就有可能一直得不到回收,发生内存泄露。2为什么key要用弱引用?事实上,在ThreadLocalMap中的set/getEntry方法中,会对key为null(也即是ThreadLocal为null)进行判断,如果为null的话,那么会把value置为null的.这就意味着使用threadLocal,CurrentThread依然运行的前提下.就算忘记调用remove方法,弱引用比强引用可以多一层保障:弱引用的ThreadLocal会被回收.对应value在下一次ThreadLocaI调用get()/set()/remove()中的任一方法的时候会被清除,从而避免内存泄漏
为什么要用ThreadLocal保存登录信息?有什么缺点和优点?
1ThreadLocal可以将用户信息保存在线程中,当请求结束后我们在把保存的信息清除掉。这样我们才开发的时候就可以直接从全局的ThreadLocal中很方便的获取用户信息。使用ThreadLocal,可以在同一线程中很方便的获取用户信息,不需要频繁的传递session对象2但是在大部分springBoot的场景下,ThreadLocal并不是必须的。一方面在线程操作外额外增加了本地线程的操作,另一方面threadLocal里的存储是静态存储,使用时需要仔细,确保多次写入时的清除覆盖,以及可能造成的gc风险