A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 小刀葛小伦 黑马粉丝团   /  2019-8-15 11:04  /  927 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

put操作
[Java] 纯文本查看 复制代码
public V put(K paramK, V paramV)
  {
    if (paramV == null)
      throw new NullPointerException();
    int i = hash(paramK.hashCode());
    return segmentFor(i).put(paramK, i, paramV, false);
  }

与HashMap不同的是,如果key为null,直接抛出NullPointer异常,之后,同样先计算hashCode的值,再计算hash值,不过此处hash函数和HashMap中的不一样:
[Java] 纯文本查看 复制代码
private static int hash(int paramInt)
  {
    paramInt += (paramInt << 15 ^ 0xFFFFCD7D);
    paramInt ^= paramInt >>> 10;
    paramInt += (paramInt << 3);
    paramInt ^= paramInt >>> 6;
    paramInt += (paramInt << 2) + (paramInt << 14);
    return (paramInt ^ paramInt >>> 16);
  }



[Java] 纯文本查看 复制代码
final Segment<K, V> segmentFor(int paramInt)
  {
    return this.segments[(paramInt >>> this.segmentShift & this.segmentMask)];
  }

根据上述代码找到Segment对象后,调用put来操作:
[Java] 纯文本查看 复制代码
V put(K paramK, int paramInt, V paramV, boolean paramBoolean)
    {
      lock();
      try {
        Object localObject1;
        Object localObject2;
        int i = this.count;
        if (i++ > this.threshold)
          rehash();
        ConcurrentHashMap.HashEntry[] arrayOfHashEntry = this.table;
        int j = paramInt & arrayOfHashEntry.length - 1;
        ConcurrentHashMap.HashEntry localHashEntry1 = arrayOfHashEntry[j];
        ConcurrentHashMap.HashEntry localHashEntry2 = localHashEntry1;
        while ((localHashEntry2 != null) && (((localHashEntry2.hash != paramInt) || (!(paramK.equals(localHashEntry2.key)))))) {
          localHashEntry2 = localHashEntry2.next;
        }
 
        if (localHashEntry2 != null) {
          localObject1 = localHashEntry2.value;
          if (!(paramBoolean))
            localHashEntry2.value = paramV;
        }
        else {
          localObject1 = null;
          this.modCount += 1;
          arrayOfHashEntry[j] = new ConcurrentHashMap.HashEntry(paramK, paramInt, localHashEntry1, paramV);
          this.count = i;
        }
        return localObject1;
      } finally {
        unlock();
      }
    }

先调用lock(),lock是ReentrantLock类的一个方法,用当前存储的个数+1来和threshold比较,如果大于threshold,则进行rehash,将当前的容量扩大2倍,重新进行hash。之后对hash的值和数组大小-1进行按位于操作后,得到当前的key需要放入的位置,从这儿开始,和HashMap一样。
从上述的分析看出,ConcurrentHashMap基于concurrentLevel划分出了多个Segment来对key-value进行存储,从而避免每次锁定整个数组,在默认的情况下,允许16个线程并发无阻塞的操作集合对象,尽可能地减少并发时的阻塞现象。在多线程的环境中,相对于HashTable,ConcurrentHashMap会带来很大的性能提升!


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马