5. HashMap如何降低Hash冲突概率( 三 )

<>();//concurrentHashMap.put("a", "a");//concurrentHashMap.put("97", "97");for (int i = 0; i < 10; i++) {concurrentHashMap.put(i + "", i + "");}//System.out.println(concurrentHashMap.get("97"));for (int i = 0; i < 10; i++) {System.out.println(concurrentHashMap.get(i + ""));}}}
7.1.2 核心参数分析
##1.无参构造函数分析:initialCapacity ---16 loadFactorHashEntry[] table; 加载因子0.75concurrencyLevel 并发级别 默认是16##2. 并发级别是能够大于2的16次方if (concurrencyLevel > MAX_SEGMENTS)concurrencyLevel = MAX_SEGMENTS;##3.sshift 左移位的次数 ssize 作用:记录segment数组大小int sshift = 0;int ssize = 1;while (ssize < concurrencyLevel) {++sshift;ssize <<= 1;}##4. segmentShift segmentMask:ssize - 1 做与运算的时候能够将key均匀存放;this.segmentShift = 32 - sshift;this.segmentMask = ssize - 1;##5. 初始化Segment0 赋值为下标0的位置Segment s0 =new Segment(loadFactor, (int)(cap * loadFactor),(HashEntry[])new HashEntry[cap]);##6.采用CAS修改复制给Segment数组UNSAFE.putOrderedObject(ss, SBASE, s0); // orPut方法底层的实现简单分析Segment s;if (value =http://www.kingceram.com/post/= null)throw new NullPointerException();###计算key存放那个Segment数组下标位置;int hash = hash(key);int j = (hash>>> segmentShift28) & segmentMask15;###使用cas 获取Segment[10]对象 如果没有获取到的情况下,则创建一个新的segment对象if ((s = (Segment)UNSAFE.getObject// nonvolatile; recheck(segments, (j << SSHIFT) + SBASE)) == null) //in ensureSegments = ensureSegment(j);### 使用lock锁对put方法保证线程安全问题return s.put(key, hash, value, false);0000 0000 00000 0000 0000 0000 0000 00110000 0000 00000 0000 0000 0000 0000 0011深度分析:Segment ensureSegment(int k) private Segment ensureSegment(int k) {final Segment[] ss = this.segments;long u = (k << SSHIFT) + SBASE; // raw offsetSegment seg;### 使用UNSAFE强制从主内存中获取 Segment对象,如果没有获取到的情况=nullif ((seg = (Segment)UNSAFE.getObjectVolatile(ss, u)) == null) {## 使用原型模式 将下标为0的Segment设定参数信息 赋值到新的Segment对象中Segment proto = ss[0]; // use segment 0 as prototypeint cap = proto.table.length;float lf = proto.loadFactor;int threshold = (int)(cap * lf);HashEntry[] tab = (HashEntry[])new HashEntry[cap];#### 使用UNSAFE强制从主内存中获取 Segment对象,如果没有获取到的情况=nullif ((seg = (Segment)UNSAFE.getObjectVolatile(ss, u))== null) { // recheck###创建一个新的Segment对象Segment s = new Segment(lf, threshold, tab);while ((seg = (Segment)UNSAFE.getObjectVolatile(ss, u))== null) {###使用CAS做修改if (UNSAFE.compareAndSwapObject(ss, u, null, seg = s))break;}}}return seg;}final V put(K key, int hash, V value, boolean onlyIfAbsent) {###尝试获取锁,如果获取到的情况下则自旋HashEntry node = tryLock() ? null :scanAndLockForPut(key, hash, value);V oldValue;try {HashEntry[] tab = table;###计算该key存放的index下标位置int index = (tab.length - 1) & hash;HashEntry first = entryAt(tab, index);for (HashEntry e = first;;) {if (e != null) {K k;###查找链表如果链表中存在该key的则修改if ((k = e.key) == key ||(e.hash == hash && key.equals(k))) {oldValue = http://www.kingceram.com/post/e.value;if (!onlyIfAbsent) {e.value = value;++modCount;}break;}e = e.next;}else {if (node != null)node.setNext(first);else###创建一个新的node结点 头插入法node = new HashEntry(hash, key, value, first);int c = count + 1;###如果达到阈值提前扩容if (c > threshold && tab.length < MAXIMUM_CAPACITY)rehash(node);elsesetEntryAt(tab, index, node);++modCount;count = c;oldValue = http://www.kingceram.com/post/null;break;}}} finally {###释放锁unlock();}return oldValue;}
7.1.3 核心Api
此方法和上面的功能类似,不过附加了’’加载语义,也就是强制从主存中获取属性值 。类似的方法有、等等 。这个方法要求被使用的属性被修饰,否则功能和方法相同 。