ThreadLocal源码解析

一、ThreadLocal的大致接触了解

1.什么是ThreadLocal?

ThreadLocal在很多地方被称作线程本地存储,意思就是ThreadLocal能为每一个线程创建一个存储空间,通过ThreadLocal能够让每一个线程存储自己的副本(set方法传需要存储的对象),这样每个线程取数据时拿到的就是自己的数据(直接调用get方法,不用传参数),这样相互之间就能不影响。

2.一个简单(蹩脚)的小例子​

public class ThreadLocalTest {
    public final static ThreadLocal<String> stringThreadLocal = new ThreadLocal<>();
    public static void main(String[] args){
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                stringThreadLocal.set("thread1");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(stringThreadLocal.get());
            }
        };
        Runnable runnable2 = new Runnable() {
            @Override
            public void run() {
                stringThreadLocal.set("thread2");
                System.out.println(stringThreadLocal.get());
            }
        };
        Thread thread1 = new Thread(runnable1);
        thread1.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Thread thread2 = new Thread(runnable2);
        thread2.start();
    }
}

代码运行结果:

顺序是线程1先是将stringThreadLocal里的String变量改为"thread1",然后线程1等待10s再把该值打印出来。线程2在线程1启动5s后启动,将stringThreadLocal里的String变量改为"thread2",马上打印(修改成功),最后线程1等待10s过后打印依然是没被线程2修改的"thread1"。

尽管stringThreadLocal是静态变量,所有的线程都共享,但是每个线程取出来的值却只跟自己有关,不会受到其他线程的影响。这就是ThreadLocal的作用,为每个线程开辟独立的存储。

3.ThreadLocal应用的场景

ThreadLocal和同步机制都是解决多线程同步问题的解决办法,不过这两者提供的是两种不同的思路:同步机制是访问对象修改对象时用锁将该对象封闭起来不准其他线程修改等,而ThreadLocal是为每个线程存一份自己的变量副本,所以ThreadLocal并不是解决共享对象的同步问题,只是从根本上避免同步问题的产生。

一般ThreadLocal适用的场景多是各个线程间没有变量共享需要的同步问题场景,比如一个简单的SimpleDateFormat类,该类不是线程安全的,却是有状态的,如果将SimpleDateFormat设置为静态的,所有线程共享,那么就会出现线程安全的问题,其中一个线程修改日期格式为“yyyyMMdd”,然后可能会影响到另外一个需要格式为“yyyy-MM-dd”的线程。但是如果在方法中每次用到的时候都new一个SimpleDateFormat类又太费内存(SimpleDateFormat这种简单的类倒还好,若是一些比较占用资源的比如数据库连接类等,就会让加大整个数据库的压力),这时候采用ThreadLocal为每一个线程保存一份SimpleDateFormat副本,这样既不会说每次调用方法都会生成一个对象,也不会在并发时产生线程同步问题。这就像是在共享一个静态变量和每次使用都new一个对象两者之间的一种折中处理方法。

 

二、ThreadLocal的原理及代码分析

1.最初的设想

在最开始用ThreadLocal的时候,潜意识里会有一种关于ThreadLocal的实现方式,ThreadLocal中保存着一份静态的Map,然后每次调用ThreadLocal的set方法时,就以当前线程为key往这个map里存放对象。

以上就是设想中的ThreadLocal的一种非常简单的实现方式。那么效果如何呢?尝试把这个“小巧”的ChenThreadLocal替换真正的ThreadLocal来跑一遍上面的示例。结果如下:

结果和使用真正的ThreadLocal是一样的结果,因为通过自定义ThreadLocal将key封装隐形掉,相关的set、get、remove方法都不能直接通过key操作,只在自定义ThreadLocal中通过Thread.getCurrentThread()方法获得key,这样能避免各个线程之间互相影响,线程就只能取到自己对应的那个对象。看上去这样也能实现ThreadLocal需要的效果,那jdk是怎么实现的呢?

2.jdk1.8的实现

ThreadLocal中实现了一个内部类,叫ThreadLocalMap用来作为对象的存储结构,然而这个存储类的实例并不存在ThreadLocal中,而是在Thread线程类中有一个该类的属性叫threadLocals,所以所有的对象存储都是在线程里,然后ThreadLocal通过某些方式(特定的方法)去对应的Thread里去存对象、取对象、去除对象。以下是三个类之间的类图:

这种方式和最初设想的方式对比起来?好处在哪?

我理解的话,因为是在ThreadLocal里维护key为Thread的map的话,因为Thread是有生命周期,如果这个thread死了,则ThreadLocal的map中对应的该thread的对象一直占用着空间,却永远不会被用到了。其实更有甚者,由于hashmap里的key指向了thread,所以这个thread都不会被回收,这是对资源的最大浪费,随着越来越多的线程产生,越来越多的内存泄漏发生,这是很恐怖的。

但是致命的一点在于,本来ThreadLocal的作用就是来处理并发问题的,如果像我们写的ThreadLocal那样还是让所有的线程的都访问同一个map,因为map是线程不安全的,所以依然会有严重的并发问题。试想,一个线程插入数据时让map扩容,扩容的同时另一个线程来插入数据,这样就会引发并发问题。

①.ThreadLocalMap的实现

A.Entry

Entry是ThreadLocalMap里实现的一个内部类,用来存放对象,一个Entry存放一个对象。这个类继承了WeakReference<ThreadLocal<?>>,然后有一个属性是Object,用来保存对象。

然后ThreadLocalMap里有一个Entry的数组,用来存放一系列的数据。从这里可以看出,ThreadLocalMap的key是ThreadLocal,value是对应的对象。

继承的WeakReference<ThreadLocal>是java提供的一个弱引用类,弱引用是指,若是一个对象只有弱引用指向它时,在下次gc时,该对象会被回收掉。

这里继承弱引用类的作用是,若是ThreadLocal对象本身不被程序用到了(即没有强引用指向它了),那就算该ThreadLocal还作为某些线程里ThreadLocalMap的key,也会被回收掉,之后就能通过一系列依据于此的操作来防止内存泄漏。

B.ThreadLocalMap的属性

ThreadLocalMap的属性比较少,只有4个属性:

C.ThreadLocalMap的存储策略(方法解析)

ThreadLocalMap的存储由一个Entry数组搞定。因为ThreadLocalMap没有设置一个loadfactor变量,所以在设置阈值的时候是写死的等于长度的2/3。

ThreadLocalMap的构造函数是default的,所以并不允许开发人员自己来实例化一个ThreadLocalMap,这是专门的用途的。构造函数有两个参数,初始想存放的key和value。构造函数中主要是做了:
1.以默认容量大小初始化一个table这个Entry数组;
2.获取firstkey的hashcode与初始容量大小-1的与运算以获的firstValue的存放位置;
3.将firstValue放到table对应的位置上;
4.设置好size、阈值;

通过key去获取ThreadLocalMap里的对象的方法是getEntry,大致流程为:
1.通过key获取对象存储的位置;
2.获取到该位置对应的对象,如果不为null且该对象的key等于参数的key,则直接返回该对象
3.如果为null或者key不相等,则调用getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e)方法来获取对应的Entry

getEntryAfterMiss方法干了以下事情:
1.如果e不为空,则看e的key是不是与查询的key相同,若是相同则直接返回e;
2.如果e不为空但是e的key为空,这说明map中有key被释放的kv对了,调用expungeStaleEntry方法(下面再详细讲expungeStaleEntry方法,这里大概也能知道这个方法做了什么);
3.如果都不是,说明没有命中,则查看下一个entry,重新来匹配;
(其实从这里可以看出ThreadLocalMap的解决冲突的策略是,发生冲突时,往下找空余的位置放置)


这边提出一个疑问?按照getEntryAfterMiss的逻辑,如果一个ThreadLocalMap容量为16,然后现在满了装了16个kv对,现在想get一个map里不存在的key,是不是会进入无限死循环?

expungeStaleEntry方法干了以下事情:


1.先将参数位置entry的value置为null,再将该位置的entry引用置为null。并且size--。
2.从该位置开始,一直往后遍历,经过的entry等于null的话退出遍历,不等于null的话进行操作:如果entry的key为null,则采取1的操作;如果key不为null,则看该key的hashcode值是否与当前位置是否一致,如果不一致,则把该entry移到对应的hashcode处,要是hashcode处已经有entry,则往后找空余的地方,然后放下。

从图就能看出一个很形象的说法就是,expungeStaleEntry其实就是每次扫描一个块,一个块的定义就是直到遇到null为止(途中的红色块)。
为什么要有这个方法?ThreadLocalMap中的entry其实是继承的弱引用,如果该弱引用指向的ThreadLocal没有在外部被强引用指向的话,在下次gc的时候就会被回收,那这样的话就会出现ThreadLocalMap中存在key为null的情况,这样的数据对于map来讲是脏数据,这样的脏数据没有用,却一直占用着map的存储空间,这其实就是一种内存泄漏,所以需要来释放掉这些空间。expungeStaleEntry方法就是为了解决内存泄漏存在的。

set方法干了以下事:


1.根据ThreadLocal的hashcode找到对应需要放置的位置。
2.从该位置开始一直往后找合适的位置放下:
——如果找到有key和参数key相同的entry,则直接把value替换成需要插入的对象
——如果找到有key为null的entry,则调用replaceStaleEntry方法
——如果遇到的entry为空,则直接放下
3.size++,然后运行cleanSomeSlots方法专门清除一些key为null的脏数据,(下面详细讲cleanSomeSlots方法)。
4.如果没有清除一个脏数据并且size已经超过阈值threshold,则调用rehash()方法重新调整大小

 

replaceStaleEntry方法干了以下事:


1.首先从指定位置参数staleSlot开始,往前找最前面的脏entry(即key为null的entry)或者直到遇到空白entry为止,遇到脏entry则用变量slotToExpunge记录位置,否则不变。
2.然后往后找,如果两者的key相同则将value覆盖掉,把该位置的对象换到staleSlot位置上去,且如果slotToExpunge与staleSlot相等,则说明第1步没有遇到脏entry,然后把slotToExpunge记录该位置。然后从slotToExpunge位置开始调用expungeStaleEntry方法,并且以返回的位置继续进行一遍cleanSomeSlots方法,cleanSomeSlots方法和expungeSatleEntry一样都是来清除脏数据并且重新整理map的(实际上clean方法里调用的就是expungeStaleEntry方法),然后直接返回。
3.如果不是2步里的key相同的情况,就判断key是不是null并且1步里没有遇到脏数据,如果是的话就用slotToExpunge记录该位置
4.将staleSlot(这个位置本来就是key为null的位置,在set方法中调用的时候传进来)位置替换成要插入的kv对。
5.如果slotToExpunge和staleSlot不相等,则clean一遍。

这个方法很复杂,看过程也会觉得很混乱,可以这样来梳理一遍,把这个方法分成两个部分来看:
——第一部分,插入部分。这部分只看关于kv的插入,这个方法的根本作用还是找到了一个key为null的位置staleSlot,然后替换成要插入的kv对。但是在插入的时候得往后找有没有key相同的entry来覆盖。所以就是两种情况:

1.找到了覆盖的,则插入kv对,并且把覆盖entry与staleSlot的key为null的entry交换位置;
2.没找到覆盖的,则直接插入到key为null的entry的位置。


——第二部分,清理部分。其实这部分是对于ThreadLocalMap的脏数据的清理以及位置的重新摆放,最后都是依赖于expungeStaleEntry方法。这个部分清理脏数据的策略很有意思,因为调用这个方法的时候是因为出现了key为null的entry,他们认为,出现脏entry的位置的附近也很有可能出现脏entry(其实我不太理解这种想法,但只能这么去猜测),所以得一直往前找碰到第一个null entry前的脏entry。接下来详细讲这个清理的策略:

1.只要往前找到了脏entry,则把slotToExpunge设为该entry的位置,直到遇到空白位置为止,clean脏数据的时候以此为起点。
2.往前没找到脏entry,往后找entry:如果entry可覆盖(key相同)则把slotToExpunge记录该位置并从这个位置清理脏数据;如果遇到key为null的脏数据,则slotToExpunge记录该位置并之后不再记录,则该位置是最前面的脏数据的位置,然后最后从这个位置开始清理脏数据。

这样就清晰明了了!

 

cleanSomeSlots方法里主要干了以下事:
1.循环log2(n)次,遇到key为null的脏数据,则在该位置开始进行expungeStaleEntry,并且刷新次数(重新又进行log2(n)次);

这种刷新的方式可能是为了平衡时间上的效率。如果log2(n)步内都没有遇到脏数据,则直接结束。若是遇到了脏数据,则再进行log2(n)次。

关于ThreadLocalMap的容量不够时会进行扩容时使用的resize()方法:


1.首先新容量是旧容量的2倍,并创建新容量大小的数组。
2.用一个临时变量count来记录有效entry个数。
3.遍历旧entry数组
——如果遇到key为null,则将value置为null。这样可以帮助gc。
——通过hashcode找到合适位置,然后判断位置是否为null,若为null则直接放下,若不为null则往后找null,然后放下。然后count++。
4.设置好size,阈值,还有新生成的entry数组。

还有一个rehash方法:
1.调用expungeStaleEntries()方法;
2.如果size大于阈值的3/4则resize();

这边为什么要判断size>3/4?rehash()只在set方法中被调用过,调用的条件是调用cleanSomeSlots方法没有清除到脏数据且此时size已经大于等于阈值,才会调用rehash。因为size已经超过阈值,所以这个时候是很需要扩容的。此时在扩容前开发者觉得还可以在抢救一下,因为扩容也算是个耗时的大操作了,就决定再全面的清理一遍脏entry,如果清理完之后size还有阈值的3/4,虽然没有超过阈值,但是如果此时不做其他处理,那么很快就要继续超阈值,又得进行一遍全面的清除。我理解的话,全面的清除的频率太高、间隙太短是没有必要且对于set操作来说是多余的操作(对于使用者来说set只是把kv对象放进来,不希望有多余的操作来占用放置操作的时间),所以一旦全面清除完成后size还有阈值的3/4,那么是时候直接进行扩容了。
expungeStaleEntries()干了以下事:
1.遍历一遍table(即entry数组)如果entry为脏entry则从这里开始expungeStaleEntry。

这里有个疑问:这样会不会做了很多无用判断?

remove方法:
1.通过hashcode找到要删除的key对应位置,判断key是不是要删除的key,如果是则调用Entry的clear方法(实际上就是继承的Reference的clear方法,将key变为null),如果不是则往后找key相同的然后调用clear方法,然后再调用expungeStaleEntry方法来清空脏数据(包括clear完的entry)

抛出一个疑问:如果有三个key算出来位置相同的对象放进ThreadLocalMap,然后这三个肯定是放置在一起相邻的,然后如果第二个清除掉变为null了,再remove方法来清除第三个,能到达第三个吗?
这里也是很有意思的,从这个疑问可以看出其实正常情况下是永远不会出现key位置相同中间却隔着null的情况的,原因很简单,是因为…………

方法简单总结:

方法

作用简单总结

ThreadLocalMap(ThreadLocal<?> firstKey,Object firstValue)

初始化ThreadLocalMap并放好第一对kv对

getEntry(ThreadLocal<?> key)

通过key去找value对象

getEntryAfterMiss(ThreadLocal<?> key,int i,Entry e)

通过key没找到对象后的操作

expungeStaleEntry(int i)

1.从i位置开始释放key为null的脏数据知道遇到Entry为null
2.途中遇到的key的hashcode和位置不对等时就重新把该entry放到key对应的位置上

set(ThreadLocal<?> key,Object value)

1.放置kv对或者覆盖kv对
2.清除脏数据
3.如果size超过阈值,则大规模清除脏数据,若是清除之后size大于阈值的3/4,则重新调整map大小

replaceStaleEntry(ThreadLocal<?> key,Object value,int slot)

1.从slot处开始找插入的位置(先找重复的key位置找不到就在slot处插)
2.清理脏数据

cleanSomeSlots(in i,int n)

从i处循环log2(n)次调用expungeStaleEntry检查
检查到脏数据重新刷新log2(n)次

expungeStaleEntries()

循环遍历整个entry来进行exPungeStaleEntry

rehash()

调用expungeStaleEntries()如果还有4/3阈值的entry则扩容resize

resize()

重新扩容,全部重新定位

 

D.ThreadLocalMap总结

看完ThreadLocalMap的源码,总结几点:
1.java虽然有gc,但是内存泄漏也是十分可怕的。
—— 将ThreadLocalMap放在Thread类中作为属性,这就是第一个典型的防止内存泄漏的例子:若是将map放在ThreadLocal中,Thread作为key,这样由于Map的强引用关系,Thread对象也永远不会被gc释放掉,导致内存泄漏,将ThreadLocalMap放在Thread中这样对象就能随着Thread的释放而被释放掉。
—— ThreadLocalMap特别怕内存泄漏,是因为ThreadLocalMap的生命周期和Thread一样,而很多时候Thread的生命周期很长,内存泄漏会导致很严重的问题,所以将ThreadLocalMap的key设置为ThreadLocal的弱引用,到时候如果ThreadLocal作废了,这个对象就会被gc释放,然后ThreadLocalMap会有一系列的释放内存的操作来防止内存泄漏。这也给我们提示,对于维护一个生命周期长的数据结构,一定要很注意内存泄漏的风险。
2.ThreadLocalMap的内存清理的核心方法就是expungeStaleEntry方法,然后这个方法除了清理掉脏数据外还会帮threadLocalMap重新定位一下entry。
3.ThreadLocalMap遇到冲突的解决策略是一个很传统的往后找“空位子”的方法。为什么这么做?我的理解是,ThreadLocalMap是给ThreadLocal做存储的专门作用的,不是通用性的Map,在ThreadLocal的场景下,需要往ThreadLocalMap里存放很多kv对的情况是很少的,加之ThreadLocal也做了相关处理来减少冲突(后面会详细讲到),所以发生冲突的概率不会很大,所以解决冲突来讲采用一种很简单的“往后探寻”的方式是很有道理的,这样既简单也高效。

 

②.ThreadLocal的实现

作为ThreadLocalMap的key,ThreadLocal的实现也是很有意思的。

A.神奇的threadLocalHashCode

在Threadlocalmap的源码中发现ThreadLocal为key时是靠他的threadLocalHashCode & (len-1) 来确定插入位置的。而ThreadLocal的这个属性如下:

所以每次创建ThreadLocal实例就会threadLocalHashCode固定的增加0x61c88647这个值。通过AtomicInteger来保证自增的线程安全。

为什么ThreadLocal的hashcode要这么做呢?让我们模拟一下这个hashcode的生成以及和其对应位置的过程,首先假如有一个ThreadLocalMap的长度是64,然后按照这个方式生成32个位置相当于插入32个数据,结果如下:

很神奇的是32个位置都没有冲突,这不禁让我们产生了一个大胆的想法~

果然就算插满了也没发生冲突。ThreadLocal的hashcode作用就出来了,这样的做法就是为了缓解冲突带来的麻烦。因为有这种设计,所以ThreadLocalMap解决冲突选择了那种很传统、很简洁的往后找空位的方法。

那么问题来了,为了解决冲突问题,hashcode选择自增一个0x61c88647值。为什么不自增1来防止冲突呢?
因为自增1会导致所有前面插入的entry都会附在一起,当发生冲突时,往后找位子会很麻烦,而0x61c88647这个值能让插入变得很均匀,不会将entry都挤在一起。

问题又来了,那为啥不自增一个其他的常量,而是0x61c88647这个看上去莫名其妙的常量?
比如自增5会是一个什么情况,对比一下5和0x61c88647的情况:

感觉不出来区别。而且5也是不会有冲突的。但是当table的容量变很大,比如table现在容量为10240,然后再看看插入32个entry的结果:

0x61c88647的位置情况:

1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000100000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000010000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000100000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000

5的位置情况:

0000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

这样一对比就可以看到,0x61c88647在2的幂次方大数下也能将位置很均匀的布置好,但是5或者其他的常量就明显在大容量下就只将数据分布在前面了。这样是很不均匀的。

B.ThreadLocal策略(方法解析)

getMap通过Thread来获取对应的ThreadLocalMap。而createMap是为ThreadLocal创建一个ThreadLocalMap,为什么会有这个方法,是因为Thread这个类创建的时候并不会去附带创建一个ThreadLocalMap对象,因为不是所有的线程都会要用到ThreadLocal,所以不用ThreadLocal的Thread早早就初始化一个ThreadLocalMap的话这样是会浪费堆内存的。所以只有在需要才会创建ThreadLocalMap的对象。


set方法是开发者与ThreadLocal交互的常用方法。这里就是很简单,获取当前线程,然后去线程里拿ThreadLocalMap,如果拿到的为null,则创建一个。

remove()方法也是开发者ThreadLocal交互的常用方法。获取ThreadLocalMap,然后调用ThreadLocalMap的remove方法移除掉对应的value。由于调用的是ThreadLocalMap的remove方法,所以这边也会有内存释放、位置重置等操作。

get()方法也是开发者ThreadLocal交互的常用方法。从ThreadLocalMap中去拿对应的value,如果没有拿到,会进行一次setInitialValue()操作。

setInitialValue()方法里用initialValue创建一个对象,然后这个在ThreadLocal里这个方法是直接返回null的,然后将这个值放进ThreadLocalMap里。但是有一个ThreadLocal的子类覆盖了这个方法。

SuppliedThreadLocal继承ThreadLocal,增加一个属性,Supplier类。Supplier是函数式编程里的一个函数式接口,用这个就能指定一个构造方法,通过supplier的get就能使用这个构造方法来创造一个实例,覆盖initialValue的实现就是利用Supllier的get方法。

说白了,SupplierThreadLocal相比ThreadLocal就是相当于增加一个生产方法,如果在threadLocal.get()方法时没有对应的对象就利用这个生产方法生产一个默认对象出来,然后放进threadLocalMap然后返回。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值