(Java基础篇)六、Java理解强引用和弱引用,以及ThreadLocal的value是强引用的原因

强引用和弱引用

  强引用和弱引用主要区别在于什么时候被垃圾回收,强引用就是我们最常使用的类型,在垃圾回收的时候,如果一个对象仅仅存在它的弱引用,那么它会被无情的回收掉。

Integer key = 666; // 强引用
WeakReference<Integer> value = new WeakReference<>(888); // 弱引用
// 另外,Integer内部IntegerCache保留了-128~127的强引用

System.gc();
// 此时key还是666  但是value = null

  在上一节中的源码深入,我发现ThreadLocalMap的key是弱引用,但是value却是个强引用,当时没想明白就没写了,现在想明白了。

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;
 
    Entry(ThreadLocal<?> k, Object v) {
    	// key在这里被变成了弱引用,方便回收
        super(k);
        value = v;
    }
}

  先说结论:key是弱引用,是因为一旦ThreadLocal<?>被回收了,那么就意味着当前线程已经不需要这个变量了,key失去了ThreadLocal<?>的强引用,就只剩ThreadLocalMap的entry的弱引用,就会被gc掉了。如果key是强引用,那么即使ThreadLocal被回收了没了,但是此时ThreadLocalMap的entry还保留着对key的强引用,那它永远不会被回收,除非线程被回收了(因为threaLocals是当前线程的成员变量)。value是强引用,这是因为key弱引用但是key引用的对象同时有ThreadLocal<?>作为强引用,在弃用前不会被gc掉,但是value没有,在set完之后如果value是弱引用,引用对象就只剩value这个弱引用了,下次gc就会被回收了。因此把value作为强引用,但是这会造成泄露的问题,不过ThreadLocalMap似乎也考虑到了,帮助我们时不时的清理key为null的entry。
value是弱引用

  上面实线代表强引用,虚线弱引用。理解之后我们看下面这个例子,帮助更深入理解一下。

public class TestWeakReference {

    public static void setMap(Map map, boolean weak, WeakReference<Integer> key) {
        // weak标注一下是不是弱引用
        if (weak) {
            WeakReference<Integer> value = new WeakReference<>(888);
            map.put(key, value);
        } else {
            map.put(key, 888);
        }
        // 静态方法手动回收一下
        System.gc();
    }

    public static void main(String[] args) throws Exception {
        Map<WeakReference<Integer>, WeakReference<Integer>> weakmap = new HashMap<>();
        Map<WeakReference<Integer>, Integer> map = new HashMap<>();
        WeakReference<Integer> key = new WeakReference<>(666);

        setMap(weakmap, true, key);
        setMap(map, false, key);

        System.out.println("从弱引用value的map中get: " + weakmap.get(key).get());
        System.out.println("从强引用value的map中get: " + map.get(key));
    }
}

输出
  最近在学习SpringSecurity,结合SecurityContextHolder也明白了value必须是强引用,否则鉴权完之后,value就不存在强引用会被回收的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值