赞
踩
作用是设置当前线程绑定的局部变量:
ThreadLocalMap
的set方法。ThreadLocalMap
的构造方法。ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue)
构造函数首先创建一个长度为16的Entry数组,然后计算出firstKey对应的索引,存储到table中,并设置size和threshold。
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1)
private final int threadLocalHashCode = nextHashCode();
private static int nextHashCode(){
return nextHashCode.getAndAdd(HASH_INCREMENT);
}
// AtomicIntger是一个提供原子操作的Intger类,通过线程安全的方式操作加减,适合高并发情况下的使用
private static AtomicIntger nextHashCode = new AtomicInteger();
// 特殊的hash值
private static final int HASH_INCREMENT = 0x61c88647;
这里定义了一个AtomicInteger类型,每次获取当前值并加上HASH_INCREMENT, HASH_INCREMENT = 0x61c88647。
这个值跟斐波那契数列(黄金分割数)有关,其主要目的是为了让哈希码能均匀的分布在2的次方的数组里,也就是Entry[] table中,这样做可以尽量避免hash冲突。
计算hash的时候里面采用了hashCode & (size - 1)的算法,这相当于取模运算hashCode % size的一个更高效的实现。
正是因为这种算法,我们要求size必须是2的整次幂,这也能保证索引在不越界的前提下,使得hash发生冲突的次数减小。
代码执行流程:
最后调用cleanSomeSlots, 清理key为null的Entry,最后返回是否清理了Entry。
接下来再判断sz是否>=threshold达到了rehash的条件,达到的话就会调用rehash函数执行一次全表的扫描清理。
该方法一次探测下一个地址,直到有空的地址后插入,若整个空间都找不到空余的地址,则产生溢出。
举个例子,假设当前table的长度为16,也就是说如果计算出来key的hash值为14,如果table[14]上已经有值,并且其key与当前key不一致,那么就发生了hash冲突,这个时候将14加1得到15,取table[15]进行判断,这个时候如果还是冲突会回到0,取table[0],以此类推,直到可以插入。
按照上面的描述,可以把Entry[] table看成一个环形数组。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。