弱引用

当被应用的强引用失去后,强引用关联的这个引用也就是虚引用相关的分配就会被回收

  

以ThreadLocal<T>为例

1.进行塞值
public void set(T value) {             
    Thread t = Thread.currentThread(); 
    ThreadLocalMap map = getMap(t);    
    if (map != null) {                 
        map.set(this, value);          
    } else {                           
        createMap(t, value);           
    }                                  
}          
2.一开始塞值肯定不存在就得走这个方法
void createMap(Thread t, T firstValue) {                           
    t.threadLocals = new ThreadLocalMap(this, firstValue);         
}          

3.里面这个firstKey就是Thread
 ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {            
     table = new Entry[INITIAL_CAPACITY];                                
     int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);      
     table[i] = new Entry(firstKey, firstValue);                         
     size = 1;                                                           
     setThreshold(INITIAL_CAPACITY);             
4.构建个Entry
 table[i] = new Entry(firstKey, firstValue);      
5.Entry里面长这样,构造参数里面有个super(k)
 static class Entry extends WeakReference<ThreadLocal<?>> {                  
     /** The value associated with this ThreadLocal. */                      
     Object value;                                                           
                                                                             
     Entry(ThreadLocal<?> k, Object v) {                                     
         super(k);                                                           
         value = v;                                                          
     }                                                                       
 }        

                                                                                                                                                                            

  

 继续看顶层引用

 默认这个queue是空,先不管它

 一直到最底层

 回头再来说,ThreadLocal的缺点,缺点有个啥来着,叫内存泄露,

 ThreadLocal<String> threadLocal = new ThreadLocal<>();//直接new一个出来,这个是强引用

        threadLocal.set("111");//塞值之后,把Thread和值放到里面的map里面去
一般情况下,threadLocal 消失后,塞值因为弱引用会被垃圾回收器回收。大并发情况下来不及回收,里面的map里面key引用的值来不及释放,没有及时被垃圾回收器回收,就造成了内存泄漏。

  于是之前讲的InheritableThreadLocal就发挥作用了。

但是据我观察,jdk17之后

虽然弱引用机制没有改变,但是 JDK 17 中内存管理方面的改进间接增强了对ThreadLocal相关内存的控制。
例如,JDK 17 的垃圾回收器(如 ZGC 和 Shenandoah GC)的优化使得内存回收更加高效和及时。 在高并发场景下,这些优化后的垃圾回收器能够更频繁地检查内存中的弱引用对象。
当ThreadLocal对象作为弱引用被回收后,
内存管理系统可以更快地识别并处理对应的ThreadLocalMap中的Entry,减少了无效Entry(键已被回收但值还在)在内存中停留的时间

  

posted @ 2024-12-26 10:32  余生请多指教ANT  阅读(17)  评论(0)    收藏  举报