关于java:ConcurrentHashMaptableSizeFor分析

39次阅读

共计 869 个字符,预计需要花费 3 分钟才能阅读完成。

ConcurrentHashMap中在创立时,会调用 tableSizeFor 办法进行计算尝试容量大小,这个办法原理就是通过奇妙的位运算,获取最靠近入参的 2 的幂次方数。
简略思考,如果这个数自身不是 2 的幂次方,如何依据这样的数,计算最靠近 2 的幂次方数呢?首先任意一个数,都能够示意为 00…01XXX…XXX, 那么最靠近它的 2 幂次方数必定是最高位左移一位,低位全 0,即:00…10000…000,那么如何失去这样的数呢?仔细观察发现,00…10000…000,其实就是 00…01111…111+ 1 得,所以问题就转为了如何求从最高位开始,低位全 1 的数,而这种数,咱们能够通过位运算 + 或运算失去。

   private static final int tableSizeFor(int c) {
        // 减一是针对入参 c 恰好是二的幂次方数
        // 此时经移位后输入应该还是 c 自身
        int n = c - 1;
        // 通过移位加或运算,使 n 最终变成 00...01111...111
        // 移 16 位为止,是因为 int 型数据,总共 32 位,挪动 16 刚好
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

举例:一个奇数
原始入参:00…01XXX…XXX1
参数减一:00…01XXX…XXX0
左移一位:00…001XX…XXX0
求或:00…011XX…XXX0
左移二位:00…00011X…XXX0
求或:00…01111x…XXX0

发现法则没?每次移 n 位 (n 为 2 的幂次方),再与移位前的数求或,会使从高位开始的 n 位变成 1,最终
移 16 位,正好变成:00…011111…1111,此时原来的数,就变成了从高位开始全 1 的数,这个时候,获取最靠近它的幂次方数就非常简单了,间接加 1,
变成:00…011111…1111–>00…100000…0000

正文完
 0