ThreadLocalMap
ThreadLocalMap是ThreadLocal的内部类,主要提供了数据存储和获取的API和存储真实数据的数据结构
我们怎么才能更好的理解这个数据机构呢,首先给出答案:其实我们被他的名字弄迷糊了,他存数据的结构其实本质上是一个Array,我们把ThreadLocalMap改名成ThreadLocalArray就很清晰了;
我们调用ThreadLocal的set方法保存数据时,会经历以下流程:
1、获得当前的线程对象
2、获得当前线程对象的ThreadLocalMap属性
3、如果ThreadLocalMap属性不为空,则调用ThreadLocalMap类的set方法
4、如果ThreadLocalMap属性为空,则通过ThreadLocalMap的构造方法创建一个ThreadLocalMap对象
ThreadLocalMap底层的数据结构是一个数组,看一下如下图就很清晰了:
Entry
首先给出答案吧,一个Entry对应的是一个 new ThreadLocal()对象执行set方法后保存的值;
比如我们项目中创建了多个ThreadLocal对象A、B、C并且每一个对象都调用了set方法,那么上面的数组就会被填充多个值;
Entry定位规则
底层原理就是根据上面的对象A、B、C计算出这些对象在Entry数组中应该占用的位置,然后将set方法传的值保存进去
定位规则是调用ThreadLocal对象A、B、C的 nextHashCode()方法然后和Entry数组的容量做余数
Entry数组是Object数组,所以可以存任何类型
nextHashCode方法
private final int threadLocalHashCode = nextHashCode();/*** The next hash code to be given out. Updated atomically. Starts at* zero.*/private static AtomicInteger nextHashCode = new AtomicInteger();/*** The difference between successively generated hash codes - turns* implicit sequential thread-local IDs into near-optimally spread* multiplicative hash values for power-of-two-sized tables.*/private static final int HASH_INCREMENT = 0x61c88647;/*** Returns the next hash code.*/private static int nextHashCode() {return nextHashCode.getAndAdd(HASH_INCREMENT);}
重点:
1、上图这一系列的数据都与当前线程绑定的,即不同线程操作ThreadLocal方法都是操作自己线程的数据,不会有线程安全问题
2、ThreadLocal可以理解成一个门面,调用其方法最终都委托到了当前线程的ThreadLocalMap
over~~