• JavaEE 多线程下的HashTable、HashMap、ConcurrentHashMap


    HashMap

    特点

    (1)HashMap是线程不安全的,意味着多线程下不能使用该方法,可能会导致意想不到的结果。如果我们细细的查看源码,就会发现HashMap方法没有synchronized这样的加锁操作。

    (2)初始化容量:HashMap的默认容量是16.把1像左移动4个字节,变成了10000,是2的4次方也就是16。put后才开辟空间。

    (3)默认加载因子:0.75f。

    (4)底层实现:数组、链表、红黑树。

            Java中的哈希表采用链地址法,当桶中的存储元素(链表)大于8的时候,进行一次判断。当数组的长度大于64的时候,自动转换成红黑树。转化成红黑树的两个必要条件:桶节点的数量大于8、整个数组的长度大于64。

    (5)如何扩容:每一次扩容大小是当前容量的2倍。当map键值对数大于等于加载因子*数组长度时,可能发生扩容;或者当某个桶的链表长度大于8,但是数组长度小于64的时候。

    (6)允许键值对中键的值为null。

    Hashtable

    特点

    (1)Hashtable的方法中,均只是简单加了synchronized关键字,在多线程下,是线程安全的。

    (2)初始化容量:初始化容量为11。

    (3)底层实现:数组和链表。

    (4)如何扩容:newsize = olesize * 2+1。拷贝过程中需要该线程完成整个扩容过程,涉及大量的元素拷贝,效率比较低。

    (5)Hashtable方法,直接使用了一把大锁,如果多个线程访问同一个Hashtable就很容易产生冲突。

    (6)不允许键值对中键的值为null。

    ConcurrentHashMap

    特点

    (1)ConcurrentHashMap方法中,针对性加锁,线程安全。

            对于读的操作,没有加锁,而是使用了volatile关键字保证了内存可见性。只对于写的操作加锁,加锁使用synchronized关键字。细化了锁的粒度。锁的时候不是直接锁住整个对象,而是每一个哈希桶,降低了锁的冲突概率。

    (2)ConcurrentHashMap更加充分的使用CAS特性,避免了出现重量级锁的情况。

    (3)针对扩容的方式进行优化,采用化零为整的策略。使用锁分段技术,把若干个哈希桶分成一个 "段" ,对每个段分别加锁。降低锁竞争的概率。

    (4)不允许键值对中键的值为null。

    三者区别

    (1)HashMap线程不安全,其他的线程安全。

    (2)Hashtable使用一把大锁,导致锁冲突概率很高,ConcurrentHashMap的每一个哈希桶使用一把锁,锁冲突的概率小。

    (3)ConcurrentHashMap相对于Hashtable使用了其他优化策略,比如使用CAS特性、使用锁分段技术等。

    (4)HashMap中,key值允许为null,另外两个不允许。

  • 相关阅读:
    jvm堆老年代内存不断被占用无法被回收之后
    介绍BootLoader、PM、kernel和系统开机的总体流程
    Python Web开发(七):登录实现及功能测试
    面试知识点【java基础篇】
    服务器存储面临的两大难题
    prometheus+process_exporter进程监控
    ESP8266-Arduino编程实例-BMP180气压温度传感器驱动
    flink读取mongodb数据源
    第102讲:MySQL多实例与Mycat分布式读写分离的架构实践
    app拉新渠道整合 一手地推、网推拉新平台整理
  • 原文地址:https://blog.csdn.net/Naion/article/details/126228595