互联网架构-Java8集合框架源码分析-047:Jdk1.8HashMap红黑树与ConcurrentHashMap源码分析

1 HashMap8为什么会引入红黑树

hashMap8中,如果链表长度>8,并且数组长度>64情况下,会将整个链表转换为红黑树,否则只是对数组扩容;
hashMap扩容将原来的数组扩容成新的数组,如果链表长度<6,红黑树转换链表。

2 HashMap8链表转红黑树实现原理1

public class MyIndex {

    @Override
    public int hashCode() {
        return 30;
    }
}
public class Test003 {
    public static void main(String[] args) {
        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
        for (int i = 1; i <= 8; i++) {
            MyIndex myIndex = new MyIndex();
            objectObjectHashMap.put(myIndex, i);
        }
        MyIndex myIndex = new MyIndex();
        objectObjectHashMap.put(myIndex, 9);
        System.out.println(objectObjectHashMap.get(myIndex)); //9
    }
}

HashMap中存放8个数据存入第9个断点调试
在这里插入图片描述
HashMap中获取第9个数据断点调试
在这里插入图片描述

3 HashMap8链表转红黑树实现原理2

public class Test003 {
    public static void main(String[] args) {
        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();

        // 数组长度提高到64
        for (int i = 1; i <= 64; i++) {
            objectObjectHashMap.put(i, i);
        }

        for (int i = 1; i <= 8; i++) {
            MyIndex myIndex = new MyIndex();
            objectObjectHashMap.put(myIndex, i);
        }
        MyIndex myIndex = new MyIndex();
        objectObjectHashMap.put(myIndex, 9);
        objectObjectHashMap.get(myIndex); //9
    }
}

红黑树转换断点调试:
在这里插入图片描述
在这里插入图片描述
HashMap8中为什么将单向链表转换双向链表+红黑树
链表长度>8 转换红黑树;链表的长度<6的情况下,红黑树转换链表
目的就是方便能够从红黑树转换成链表

数组扩容的时候,重新计算index值。如果新链表长度<6的情况下,不会使用红黑树存放,否则情况下采用红黑树。

4 HashTable与HashMap存在的区别

课程内容:
1.为什么要使用ConcurrentHashMap
2.ConcurrentHashMap分段锁实现原理
3.Jdk1.8与1.7实现ConcurrentHashMap区别

hashMap与hashTable区别:
hashTable线程安全,hashMap线程不安全;
hashTable不允许存放key为空,hashMap允许存放key为空;

hashTable存在哪些弊端?
hashTable底层采用synchronized解决线程安全问题,在多线程情况下只允许一个线程对put方法实现操作,多线程变成单线程在执行,效率低。
既想要线程安全又想要多线程情况提高效率,使用ConcurrentHashMap。

5 HashTable线程安全存在那些问题

在这里插入图片描述
hathTable多线程情况下执行put方法的时候,使用synchronized把整个table数组所有链表全部锁住,只有一个线程可以操作。

6 ConcurrentHashMap分段锁技术原理分析

Jdk1.7的ConcurrentHashMap采用分段锁技术
ConcurrentHashMap会默认分成16个不同的小的hashTable,然后再通过一些计算方式在多线程的情况下,让每个键值对到不同的hashTable存放,从而能够解决多线程的效率问题,也能保证线程安全的问题。
注意:理论上最多只有16个线程同时能够对ConcurrentHashMap实现操作,ConcurrentHashMap设置好了小的hashTable,后期是无法扩容的。
Jdk1.8的ConcurrentHashMap删除分段锁技术,改用CAS无锁机制+synchronized。

7 基于HashTable手写分段锁技术

public class MyConcurrentHashMap<K, V> {
    private Hashtable<K, V>[] hashtables;

    public MyConcurrentHashMap() {
        // 默认分成16个hashtables
        hashtables = new Hashtable[16];
    }

    public void put(K k, V v) {
        // 1.获取hash值
        int hash = hash(k);
        // 2.计算index值
        int index = hash & (hashtables.length - 1);
        // 3.获取对应的hashtable
        Hashtable hashtable = hashtables[index];
        if (hashtable == null) {
            // 多线程new可能有线程安全问题 解决方案:锁、cas、预热机制(提前创建)
            hashtable = new Hashtable();
        }
        hashtable.put(k, v);
        hashtables[index] = hashtable;
    }

    public V get(K k) {
        // 1.获取hash值
        int hash = hash(k);
        // 2.计算index值
        int index = hash & (hashtables.length - 1);
        // 3.获取对应的hashtable
        Hashtable hashtable = hashtables[index];
        if (hashtable == null) {
            return null;
        }
        return (V) hashtable.get(k);
    }


    private int hash(Object k) {
        // hashSeed
        return 0 ^ k.hashCode();
    }
}
public class Test004 {
    public static void main(String[] args) {
        MyConcurrentHashMap concurrentHashMap = new MyConcurrentHashMap();
        concurrentHashMap.put("mayikt","zhangsan");
        System.out.println(concurrentHashMap.get("mayikt")); //zhangsan
    }
}

8 Jdl1.7ConcurrentHashMap源码分析

Jdk1.7ConcurrentHashMap源码分析:
1.分成16个不同的Segment,每个Segment有自己独立的table,本质上就是hashTable;,底层继承ReentrantLock;
2.根据key计算index存放在Segment位置。
ConcurrentHashMap —> Segment(HashTable) —> HashEntry

9 Jdk1.8ConcurrentHashMap源码分析

Jdk1.7ConcurrentHashMap底层采用分段锁,也就是每个Segment都有自己独立的锁;
Jdk1.8ConcurrentHashMap底层采用Cas无锁机制+synchronized。
在这里插入图片描述
New Node采用cas乐观锁机制保障线程安全性问题;如果index产生冲突,使用synchronized上锁。节点维度上锁,锁的粒度相比jdk1.7更加精细。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值