ThreadLocal原理及魔数0x61c88647

ThreadLocal内存泄漏问题

根据上面Entry方法的源码,我们知道ThreadLocalMap是使用ThreadLocal的弱引用作为Key的。下图是本文介绍到的一些对象之间的引用关系图,实线表示强引用,虚线表示弱引用:

如上图,ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal没有外部强引用引用他,那么系统gc的时候,这个ThreadLocal势必会被回收,这样一来,ThreadLocalMap中就会出现key为null的Entry,就没有办法访问这些key为null的Entry的value,如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:
Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value
永远无法回收,造成内存泄露。

ThreadLocal的hashcode

ThreadLocalMap中都需要根据索引i来get,set

 int i = key.threadLocalHashCode & (len-1);

这里关键的threadLocalHashCode

下面仿照ThreadLocal来跑threadLocalHashCode

单线程,多实例化

public class ThreadLocalMapDemo {

    private final int threadLocalHashCode = nextHashCode();

    private static AtomicInteger nextHashCode =
            new AtomicInteger();

    private static final int HASH_INCREMENT = 0x61c88647;

    private static int nextHashCode() {
        return nextHashCode.getAndAdd(HASH_INCREMENT);
    }

    public static void main(String[] args) {
        System.out.println(new ThreadLocalMapDemo().threadLocalHashCode);
        System.out.println(new ThreadLocalMapDemo().threadLocalHashCode);
        System.out.println(new ThreadLocalMapDemo().threadLocalHashCode);
        System.out.println(new ThreadLocalMapDemo().threadLocalHashCode);
    }
}

Output:

0
1640531527
-1013904242
626627285

多线程,单实例化

public class ThreadLocalMapDemo {

    private final int threadLocalHashCode = nextHashCode();

    private static AtomicInteger nextHashCode =
            new AtomicInteger();

    private static final int HASH_INCREMENT = 0x61c88647;

    private static int nextHashCode() {
        return nextHashCode.getAndAdd(HASH_INCREMENT);
    }

    public static void main(String[] args) {
        for(int i=0;i<5;i++){
            new Thread(() -> {
                System.out.println("threadName:"+Thread.currentThread().getName()+":"+new ThreadLocalMapDemo().threadLocalHashCode);
            }).start();
        }
    }
}

Output:

threadName:Thread-0:0
threadName:Thread-1:1640531527
threadName:Thread-2:-1013904242
threadName:Thread-3:626627285
threadName:Thread-4:-2027808484

魔数0x61c88647

参考:

Java进阶(七)正确理解Thread Local的原理与适用场景

ThreadLocal源码详细解析、魔数0x61c88647

ThreadLocal的hash算法(关于 0x61c88647)

彻底理解ThreadLocal

猜你喜欢

转载自www.cnblogs.com/hongdada/p/12108611.html
今日推荐