【翻译】Java ConcurrentHashMap的最佳实践

【翻译】Java ConcurrentHashMap的最佳实践

原文地址: Java ConcurrentHashMap Bset Practices

         ConcurrentHashMap除了提供了与 HashMap类似的功能外,内部实现了同步机制。这意味着,我们当我们需要在多线程应用中使用 ConcurrentHashMap时不再需要使用 synchronized块。

        //Initialize ConcurrentHashMap instance
        ConcurrentHashMap<String, Integer> m = new ConcurrentHashMap<>();
        m.put("id-1", 1);
        m.put("id-2", 2);
        m.put("id-3", 3);
        //Print all values stored in ConcurrentHashMap instance
        for(Entry<String,Integer> e : m.entrySet()){
            System.out.println(threadName + ": " + e.getKey() + " = " + e.getValue());
        }  

        上述代码确保了应该在多线程环境下运行的合理有效。为什么用合理有效这个词来描述呢,因为上述代码兼顾了线程安全和代码的运行效率。ConcurrentHashMap的引入,就是在确保线程安全的同时改进代码运行的效率。那么,ConcurrentHashMap是如何做到的呢?
        要解释这个问题,我们就需要理解ConcurrentHashMap类的内部工作原理。首先,我们来看看ConcurrentHashMap类构造函数的参数列表。参数最多的构造函数需要传入三个参数:
1. initialCapacity
2. loadFactor
3. concurrencyLevel

        从命名上来看,前面两个参数非常容易理解,但最后一个参数名字就比较晦涩。最后一个参数代表了数据的片段数量。这个数量用来将ConcurrentHashMap数据内部划分为多个部分,同时创建相同数量的线程对ConcurrentHashMap数据进行维护。
ConcurrentHashMap
        concurrencyLevel缺省值为16,也就是说,当我们使用ConcurrentHashMap的默认构造函数创建一个实例时,在添加第一个键值对前,ConcurrentHashMap就拥有了16个数据片段。意味着,创建了16个各内部类的实例,如:ConcurrentHashMap$SegmentConcurrentHashMap$HashEntry[]以及ReentrantLock$NonfairSync
一般应用程序中的多数场景,用多线程处理单个键值对数据量合理的数据片段时,性能表现并不差。使用多个数据片段会让内部处理变得时常复杂,并且还会为垃圾回收带来大量不必要的对象,这些对程序性能都会有影响。
        使用默认构造函数来创建ConcurrentHashMap一个对象会额外创建1%至50%的其它对象。因此,100个这样的ConcurrentHashMap对象就会有5000个额外创建的对象。
        基于以上的分析,我们建议使用合理的构造函数参数,来减少不必要的对象数量,以提高性能。
一个好的初始化方法是如下形式:

ConcurrentHashMap<String, Integer> instance = new ConcurrentHashMap<>(16,0.9f,1);

        容量参数16来减少或避免Map的扩容。负载因子0.9保证ConcurrentHashMap的数据空集程序,以优化内存的使用。concurrentLevel设置为1确保内部只需要创建和维护一个数据片段。
        需要注意的是,如果开发的是一个高并发应用,并且对ConcurrentHashMap的更新频率非常高,我们就需要考虑使用大于1的值来设置concurrentLevel,但这个数字需要分析我们的应用场景来设计。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值