ThreadLocal原理

简介: 经典八股文之ThreadLocal原理

Java相关文章


ThreadLocal原理

  1. ThreadLocal对象new出来存放到堆中,ThreadLocal引用是存放在栈里
  2. Thread 类有个 ThreadLocalMap 成员变量,Map的key是Threadlocal 对象,value是你要存放的线程局部变量。
publicvoidset(Tvalue) {
//获取当前线程Thread,就是上图画的Thread 引用Threadt=Thread.currentThread(); 
//Thread类有个成员变量ThreadlocalMap,拿到这个MapThreadLocalMapmap=getMap(t);
if (map!=null)
//this指的就是Threadlocal对象map.set(this, value);
elsecreateMap(t, value);
}
ThreadLocalMapgetMap(Threadt) {
//获取线程的ThreadLocalMapreturnt.threadLocals;
}
voidcreateMap(Threadt, TfirstValue) {
//初始化t.threadLocals=newThreadLocalMap(this, firstValue);
}
  1. ThreadLocalMap 类的定义在 Threadlocal中。结构与HashMap一样
  2. 使用ThreadLocal后一定手动remove掉
  1. 引用ThreadLocal的对象被回收了,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。value在下一次ThreadLocalMap调用set、get、remove的时候会被清除。
  1. ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用。


既然是线程局部变量,那为什么不用线程对象(Thread对象)作为key,这样不是更清晰,直接用线程作为key获取线程变量?

  1. 这样设计会有个问题,比如: 我已经把用户信息存在线程变量里了,这个时候需要新增加一个线程变量,比方说新增用户地理位置信息
  2. 我们ThreadlocalMap 的key用的是线程,再存一个地理位置信息,key都是同一个线程(key一样),会覆盖原来的用户信息。


为什么ThreadLocal中的key设计成WeakReference

ThreadLocal<UserInfo>userInfoThreadLocal=newThreadLocal<>();
userInfoThreadLocal.set(userInfo);
  1. 为了尽大可能的避免内存泄漏
  2. new出的ThreadLocal被userInfoThreadLocal强引用,同时也被ThreadLocalMap的Key弱引用
  3. gc要回收ThreadLocal对象的前提是它只被WeakReference引用
  4. 所以只要ThreadLocal对象如果还被 userInfoThreadLocal(强引用) 引用着,GC是不会回收被WeakReference引用的对象的。
  5. 有些线程会用线程池优化,线程生命周期很长,根据JVM 根搜索算法,一直存在 Thread -> ThreadLocalMap -> Entry(元素)这样一条引用链路,如果key不设计成WeakReference类型,是强引用的话,就一直不会被GC回收,key就一直不会是null,不为null Entry元素就不会被清理(ThreadLocalMap是根据key是否为null来判断是否清理Entry)
  6. 所以ThreadLocal的设计者认为只要ThreadLocal 所在的作用域结束了工作被清理了,GC回收的时候就会把key引用对象回收,key置为null,ThreadLocal会尽力保证Entry清理掉来最大可能避免内存泄漏。
  7. ThreadLocalMap中Entry 继承了WeakReference类,Entry 中的 key 是WeakReference类型的,在Java 中当对象只被 WeakReference 引用,没有其他对象引用时,被WeakReference 引用的对象发生GC 时会直接被回收掉。




相关文章
|
6月前
|
存储 安全 Java
面试题:用过ThreadLocal吗?ThreadLocal是在哪个包下的?看过ThreadLocal源码吗?讲一下ThreadLocal的get和put是怎么实现的?
字节面试题:用过ThreadLocal吗?ThreadLocal是在哪个包下的?看过ThreadLocal源码吗?讲一下ThreadLocal的get和put是怎么实现的?
78 0
|
3月前
|
存储 设计模式 安全
深入理解ThreadLocal原理
本文深入探讨了Java中的ThreadLocal及其内部数据结构ThreadLocalMap的工作原理和特性,帮助读者理解如何利用ThreadLocal实现线程局部变量的隔离和线程安全。
深入理解ThreadLocal原理
|
4月前
|
存储 算法 Java
ThreadLocal 源码浅析
【7月更文挑战第5天】`ThreadLocal` 是Java中用于创建线程局部变量的工具类,确保每个线程拥有独立的变量副本。源码中,每个`ThreadLocal`实例都有一个唯一的哈希码用于映射到`ThreadLocalMap`,这个内部静态类使用弱引用存储键(`ThreadLocal`实例)以防止内存泄漏。`ThreadLocalMap`使用 Entry 数组,Entry 是一个扩展了 WeakReference 的类,持有线程变量值。`ThreadLocal`的`get()`和`set()`方法通过哈希计算定位并访问或设置线程局部变量。
|
6月前
|
存储 安全 Java
ThreadLocal原理讲解
ThreadLocal原理讲解
56 0
|
存储 Java
大厂是怎么用ThreadLocal?ThreadLocal核心原理分析
ThreadLocal**是Java中的一个线程本地变量类。它可以让每个线程都有自己独立的变量副本,而不会相互影响。
119 1
|
Java 数据库连接
ThreadLocal原理和实践
ThreadLocal是线程本地变量,解决多线程环境下成员变量共享存在的问题。ThreadLocal为每个线程创建独立的的变量副本,他的特性是该变量的引用对全局可见,但是其值只对当前线程可用,每个线程都将自己的值保存到这个变量中而各线程不受影响。
162 0
ThreadLocal原理和实践
|
存储 SpringCloudAlibaba Java
浅析ThreadLocal使用及实现原理
提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其`get` 或 `set`方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。`ThreadLocal`实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联 。所以ThreadLocal与线程同步机制不同,线程同步机制是多个线程共享同一个变量,而ThreadLocal是为每一个线程创建一个单独的变量副本,故而每个线程都可以独立地改变自己所拥有的变量副本,而不会影响其他线程所对应的副本。可以这么说Th
109 0
浅析ThreadLocal使用及实现原理
|
存储 算法 安全
ThreadLocal原理剖析
ThreadLocal原理剖析
222 0
|
存储 安全 Java
ThreadLocal源码分析
ThreadLocal,即线程局部变量。主要用于线程间数据隔离。这些变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量,ThreadLocal实例通常来说都是private static类型。ThreadLocal不是为了解决多线程访问共享变量,而是为每个线程创建一个单独的变量副本,提供了保持对象的方法和避免参数传递的复杂性。