首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java ConcurrentHashMap比HashMap性能好吗?

Java ConcurrentHashMap比HashMap性能好吗?
EN

Stack Overflow用户
提问于 2011-07-14 18:48:07
回答 4查看 15.7K关注 0票数 25

我刚刚读了“干净的代码”这本书,偶然发现了这样一句话:

在Java很小的时候,Doug Lea就用Java语言编写了开创性的book8并发编程。除了这本书,他还开发了几个线程安全的集合,这些集合后来成为java.util.concurrent包中JDK的一部分。该包中的集合对于多线程情况是安全的,并且它们执行得很好。事实上, ConcurrentHashMap 实现在几乎所有情况下都比HashMap在中执行得更好。它还允许并发读取和写入,并且它具有支持通用复合操作的方法,否则这些复合操作就不是线程安全的。如果Java5是部署环境,则从ConcurrentHashMap开始

请注意,在上面的引用中,我使用了"n",其中n是某个数字,以指示作者提供参考的地方,正如您可以看到的那样,他没有为粗体部分提供任何参考。

并不是我不相信这一说法,但我很想知道这一说法的支持证据。那么,有没有人知道可以同时显示ConcurrentHashMapHashMap性能统计信息的资源?或者有人能给我解释一下为什么ConcurrentHashMap比HashMap快?

我可能会在休息的时候研究一下ConcurrentHashMap在工作中的实现,但现在我希望从SOers同事那里听到答案。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-07-15 05:17:16

Doug Lea非常擅长这些事情,所以如果有一次他的ConcurrentHashMap比Joshua Bloch的HashMap表现更好,我也不会感到惊讶。然而,从Java7开始,HashMap的第一个@作者也变成了Doug Lea。显然,现在HashMap没有理由比它的并发表亲慢。

出于好奇,我还是做了一些基准测试。我在Java7下运行,条目越多,性能越接近。最终,ConcurrentHashMapHashMap的3%以内,这是相当值得注意的。瓶颈实际上是内存访问,俗话说得好,“内存就是新的磁盘(而磁盘就是新的磁带)”。如果条目在缓存中,则两者都是快速的;如果条目不能放入缓存中,则两者都将变慢。在实际应用中,地图并不一定要很大才能与其他地图竞争缓存中的内容。如果地图经常被使用,它就会被缓存;如果不经常使用,它就不会被缓存,而这才是真正的决定因素,而不是实现(假设两者都是由同一个专家实现的)

代码语言:javascript
复制
public static void main(String[] args)
{
    for(int i = 0; i<100; i++)
    {
        System.out.println();

        int entries = i*100*1000;
        long t0=test( entries, new FakeMap() );
        long t1=test( entries, new HashMap() );
        long t2=test( entries, new ConcurrentHashMap() );

        long diff = (t2-t1)*100/(t1-t0);
        System.out.printf("entries=%,d time diff= %d%% %n", entries, diff);
    }
}


static long test(int ENTRIES, Map map)
{
    long SEED = 0;
    Random random = new Random(SEED);

    int RW_RATIO = 10;

    long t0 = System.nanoTime();

    for(int i=0; i<ENTRIES; i++)
        map.put( random.nextInt(), random.nextInt() );

    for(int i=0; i<RW_RATIO; i++)
    {
        random.setSeed(SEED);
        for(int j=0; j<ENTRIES; j++)
        {
            map.get( random.nextInt() );
            random.nextInt();
        }
    }
    long t = System.nanoTime()-t0;
    System.out.printf("%,d ns %s %n", t, map.getClass());
    return t;
}


static class FakeMap implements Map
{
    public Object get(Object key)
    {
        return null;  
    }
    public Object put(Object key, Object value)
    {
        return null;  
    }
    // etc. etc.
}
票数 15
EN

Stack Overflow用户

发布于 2011-07-14 19:02:58

如果你只用一个线程访问HashMap,HashMap是最快的(它不做任何同步),如果你从多个线程访问它,ConcurrentHashMap比手工进行粗粒度的同步要快。这里有一个小小的比较:

http://www.codercorp.com/blog/java/why-concurrenthashmap-is-better-than-hashtable-and-just-as-good-hashmap.html

票数 12
EN

Stack Overflow用户

发布于 2013-04-19 15:08:36

HashMap可能较慢的原因是因为它必须检测ConcurrentModification才能知道何时抛出异常。ConcurrentHashMap不需要检查modCount就能知道什么时候抛出(但它确实将它用于size()和isEmpty())。获取锁是非常快的,特别是在单线程的情况下,当您已经持有锁,但检查modCount是两次读取和一个跳转,如果不等于,HashMap必须支付抛出CoModException。

我建议您阅读您的集合类的源代码,这样您就可以在进行方法调用时知道它们正在做多少工作。当你只有一个完全私有的map用于字典get/put的时候,你通常可以使用一个没有任何modCount甚至大小跟踪的精简的HashMap来提升性能。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6692008

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档