zoukankan      html  css  js  c++  java
  • 如何在很短的时间内将大量数据插入到ConcurrentHashMap(转)

    将大批量数据保存到map中有两个地方的消耗将会是比较大的:第一个是扩容操作,第二个是锁资源的争夺。第一个扩容的问题,主要还是要通过配置合理的容量大小和扩容因子,尽可能减少扩容事件的发生;第二个锁资源的争夺,在put方法中会使用synchonized对头节点进行加锁,而锁本身也是分等级的,因此我们的主要思路就是尽可能的避免锁等级。所以,针对第二点,我们可以将数据通过通过ConcurrentHashMap的spread方法进行预处理,这样我们可以将存在hash冲突的数据放在一个组里面,每个组都使用单线程进行put操作,这样的话可以保证锁仅停留在偏向锁这个级别,不会升级,从而提升效率。

    其他:

    ConcurrentHashMap 1.7和1.8的区别
    1、整体结构
    1.7:Segment + HashEntry + Unsafe

    1.8: 移除Segment,使锁的粒度更小,Synchronized + CAS + Node + Unsafe

    2、put()
    1.7:先定位Segment,再定位桶,put全程加锁,没有获取锁的线程提前找桶的位置,并最多自旋64次获取锁,超过则挂起。

    1.8:由于移除了Segment,类似HashMap,可以直接定位到桶,拿到first节点后进行判断,1、为空则CAS插入;2、为-1则说明在扩容,则跟着一起扩容;3、else则加锁put(类似1.7)

    3、get()
    基本类似,由于value声明为volatile,保证了修改的可见性,因此不需要加锁。

    4、resize()
    1.7:跟HashMap步骤一样,只不过是搬到单线程中执行,避免了HashMap在1.7中扩容时死循环的问题,保证线程安全。

    1.8:支持并发扩容,HashMap扩容在1.8中由头插改为尾插(为了避免死循环问题),ConcurrentHashmap也是,迁移也是从尾部开始,扩容前在桶的头部放置一个hash值为-1的节点,这样别的线程访问时就能判断是否该桶已经被其他线程处理过了。

    5、size()
    1.7:很经典的思路:计算两次,如果不变则返回计算结果,若不一致,则锁住所有的Segment求和。

    1.8:用baseCount来存储当前的节点个数,这就设计到baseCount并发环境下修改的问题(说实话我没看懂-_-!)。

    JDK1.7中扩容中转移数组transfer()方法源码。

    void transfer(Entry[] newTable, boolean rehash) {
        //新table的容量
        int newCapacity = newTable.length;
        //遍历原table
        for (Entry<K,V> e : table) {
            while(null != e) {
                //保存下一次循环的 Entry<K,V>
                Entry<K,V> next = e.next;
                if (rehash) {
                    //通过e的key值计算e的hash值
                    e.hash = null == e.key ? 0 : hash(e.key);
                }
                //得到e在新table中的插入位置
                int i = indexFor(e.hash, newCapacity);
                //采用链头插入法将e插入i位置,最后得到的链表相对于原table正好是头尾相反的
                e.next = newTable[i];
                newTable[i] = e;
                //下一次循环
                e = next;
            }
        }
    }


    原文链接:https://blog.csdn.net/u013374645/article/details/88700927

  • 相关阅读:
    HBase 高性能加入数据
    Please do not register multiple Pages in undefined.js 小程序报错的几种解决方案
    小程序跳转时传多个参数及获取
    vue项目 调用百度地图 BMap is not defined
    vue生命周期小笔记
    解决小程序背景图片在真机上不能查看的问题
    vue项目 菜单侧边栏随着右侧内容盒子的高度实时变化
    vue项目 一行js代码搞定点击图片放大缩小
    微信小程序进行地图导航使用地图功能
    小程序报错Do not have xx handler in current page的解决方法
  • 原文地址:https://www.cnblogs.com/Esquecer/p/11418350.html
Copyright © 2011-2022 走看看