ThreadLocal的hashCode为什么不直接使用1,2,3,4,5自增?

每个ThreadLocal都有一个threadLocalHashCode,根据该值去选择对应的Entry[]位置,并且 每个都是调用nextHashCode,为什么不直接使用1,2,3,4,5呢?

public class ThreadLocal<T> {
    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); 
    }

     //table的长度必须是2的N次方
    private Entry[] table;
    //还有其他类和方法。
}

我觉得主要原因,threadLocal会被清除的,threadLocal=null 的虚引用的自动清除(下次set、get时会清除),还是threadLocal.clear()主动清除,会调用到private int expungeStaleEntry(int staleSlot)方法。该方法会size--; 也就是把无效的清除掉 也就不占用Entry[]的空间了,不容易达到阈值了扩容次数就会被减少。

而如果使用1,2,3.....16 就会一直递增,如果2、3、4变为null了,采用什么方案呢?

方案1:不管,继续增加扩容。 缺点占用更大空间。

方案2:也可以size--,但是这样发生碰撞的概率更大,例如1一直有值,因此第17过来,17%16=1一定会发生碰撞。发生碰撞概率更大。而nextHashCode.getAndAdd(0x61c88647) 更随机,更不容易碰撞,及时碰撞,线性探测法解决hash冲突。

测试用例:

    private static final int HASH_INCREMENT = 0x61c88647;
    public static void main(String[] args) {
        magicHash(16); //初始大小16
        magicHash(32); //扩容一倍
    }
 
    private static void magicHash(int size){
        int hashCode = 0;
        for(int i=0;i<size;i++){
            hashCode = i*HASH_INCREMENT+HASH_INCREMENT;
            System.out.print((hashCode & (size-1))+" ");
        }
        System.out.println();
    }

实验结果: 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值