简体   繁体   English

Java ConcurrentHashMap 在性能方面优于 HashMap 吗?

[英]Java ConcurrentHashMap is better than HashMap performance wise?

I was just reading the book Clean Code and came across this statement:我刚刚在阅读《清洁代码》这本书,并遇到了这样的声明:

When Java was young Doug Lea wrote the seminal book[8] Concurrent Programming in Java.当 Java 年轻时,Doug Lea 在 Java 中写了开创性的著作 [8] 并发编程。 Along with the book he developed several thread-safe collection, which later became part of the JDK in the java.util.concurrent package.随书一起他开发了几个线程安全的集合,这些集合后来成为 JDK 中java.util.concurrent package 的一部分。 The collections in that package are safe for multithreaded situations and they perform well. collections package 在多线程情况下是安全的,并且性能良好。 In fact, the ConcurrentHashMap implementation performs better than HashMap in nearly all situations.事实上,在几乎所有情况下, ConcurrentHashMap实现都比 HashMap 执行得更好 It also allows for simultaneous concurrent reads and writes, and it has methods supporting common composite operations that are otherwise not thread safe.它还允许同时并发读取和写入,并且它具有支持普通复合操作的方法,否则这些操作不是线程安全的。 If Java 5 is the deployment environment, start with ConcurrentHashMap如果Java 5是部署环境,则从ConcurrentHashMap开始

Note that in the above quote I used "[n]", where n is some number, to indicate the places where the author provided references, and as you can see he did not provide any reference for the bold part.请注意,在上面的引用中,我使用了“[n]”,其中 n 是某个数字,表示作者提供参考的地方,正如您所见,他没有为粗体部分提供任何参考。

Not that I don't believe this statement, but I would love to know the supporting evidences of this statement.不是我不相信这个说法,而是我很想知道这个说法的支持证据。 So, does anyone know any resources that shows the performance statistics for both ConcurrentHashMap and HashMap ?那么,有谁知道任何显示ConcurrentHashMapHashMap的性能统计数据的资源? Or can anyone explain to me why ConcurrentHashMap is faster than HashMap?或者谁能向我解释为什么 ConcurrentHashMap 比 HashMap 快?

I probably will look into ConcurrentHashMap's implementation at work when I'm taking a break, but for now I would like to hear the answers from fellow SOers.我可能会在休息时研究 ConcurrentHashMap 在工作中的实现,但现在我想听听其他 SOers 的答案。

Doug Lea is extremely good at these things, so I won't be surprised if at one time his ConcurrentHashMap performs better than Joshua Bloch's HashMap . Doug Lea 非常擅长这些事情,所以如果有一次他的ConcurrentHashMap性能优于 Joshua Bloch 的HashMap ,我不会感到惊讶。 However as of Java 7, the first @author of HashMap has become Doug Lea too.然而,从 Java 7 开始, HashMap的第一作者 @author 也成为了 Doug Lea。 Obviously now there's no reason HashMap would be any slower than its concurrent cousin.显然,现在没有理由HashMap会比它的并发表亲慢。

Out of curiosity, I did some benchmark anyway.出于好奇,我还是做了一些基准测试。 I run it under Java 7. The more entries there are, the closer the performance is.我在Java 7下运行,条目越多,性能越接近。 Eventually ConcurrentHashMap is within 3% of HashMap , which is quite remarkable.最终ConcurrentHashMapHashMap的 3% 以内,这是相当了不起的。 The bottleneck is really memory access, as the saying goes, "memory is the new disk (and disk is the new tape)".瓶颈真的是memory访问,俗话说“内存是新磁盘(磁盘是新磁带)”。 If the entries are in the cache, both will be fast;如果条目在缓存中,两者都会很快; if the entries don't fit in cache, both will be slow.如果条目不适合缓存,两者都会很慢。 In real applications, a map doesn't have to be big to compete with others for residing in cache.在实际应用中,map 不必很大就可以与其他人竞争驻留在缓存中。 If a map is used often, it's cached;如果经常使用 map,它会被缓存; if not, it's not cached, and that is the real determining factor, not the implementations (given both are implemented by the same expert)如果不是,它不会被缓存,这是真正的决定因素,而不是实现(假设两者都是由同一个专家实现的)

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.
}

If you are accessing the HashMap with only a single thread HashMap is fastest (it does not do any synchronization), if you are accessing it from multiple threads ConcurrentHashMap is faster than doing the synchronization coarse-grained by hand.如果您仅使用单线程访问 HashMap HashMap 最快(它不执行任何同步),如果您从多个线程访问它,则 ConcurrentHashMap 比手动进行粗粒度同步更快。 See here for a little comparison:请参阅此处进行一些比较:

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

The reason a HashMap could be slower is because it has to detect ConcurrentModification to know when to throw an exception. HashMap 可能较慢的原因是它必须检测 ConcurrentModification 才能知道何时抛出异常。 ConcurrentHashMap does not have to check modCount to know when to throw (but it does use it for size() and isEmpty()). ConcurrentHashMap 不必检查 modCount 以知道何时抛出(但它确实将它用于 size() 和 isEmpty())。 Acquiring a lock is very fast, especially so in single-threaded situations when you already hold the lock, but checking modCount is two reads and a jump-if-not-equal that HashMap must pay to throw CoModException.获取锁非常快,尤其是在单线程情况下,当您已经持有锁时,但检查 modCount 是两次读取和一次不相等跳转,HashMap 必须支付才能抛出 CoModException。

I recommend reading the source of your collections classes, so you know how much work they are doing when you make a method call.我建议阅读您的 collections 类的源代码,这样您就知道在进行方法调用时它们做了多少工作。 In situations when you have a completely private map for dictionary get/put only, you can often used a stripped down HashMap without any modCount or even size tracking for added performance boost.在您有一个完全私有的 map 仅用于字典获取/放置的情况下,您通常可以使用精简的 HashMap 而不使用任何 modCount 甚至大小跟踪来增加性能提升。

This is the kind of rubbery statement that is hard to prove one way or the other.这是一种很难以一种或另一种方式证明的橡胶陈述。 How do you measure something in "nearly all situations" ?您如何在“几乎所有情况”中衡量某事?

A ConcurrentHashMap is likely to be better than a synchronized HashMap . ConcurrentHashMap可能比同步的HashMap更好。 The more contention there is, the more significant the difference will be.争论越多,差异就越大。 On the other hand an unsynchronized HashMap is likely to be faster than a ConcurrentHashMap , because of the overhead of unnecessary locking in the latter case.另一方面,不同步的HashMap可能比ConcurrentHashMap更快,因为在后一种情况下不必要的锁定开销。


I'd also like to see the context for that statement, and what evidence the book's author puts forward to support it.我还想了解该声明的上下文,以及该书作者提出的支持该声明的证据。 And the evidence for the unstated assumption that "nearly all" use-cases for hash maps involve synchronization.以及未说明的假设的证据,即 hash 地图的“几乎所有”用例都涉及同步。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 有没有比ConcurrentHashMap具有更好性能的并发映射? - Any concurrent maps with better performance than ConcurrentHashMap? Java中同步Hashmap vs ConcurrentHashMap的性能评估 - Performance evaluation of synchronized Hashmap vs ConcurrentHashMap in Java 性能 ConcurrentHashmap 与 HashMap - Performance ConcurrentHashmap vs HashMap Java控制器上的HashMap或ConcurrentHashMap? - HashMap or ConcurrentHashMap at Java Controllers? Java并发:HashMap和ConcurrentHashMap的“get(Key)”性能相同吗? - Java Concurrency: Are "get(Key) for HashMap and ConcurrentHashMap equal in performance? 使用redis缓存java对象:为什么它应该比ConcurrentHashMap更好? - Using redis to cache java objects: why it should be better than a ConcurrentHashMap? JAVA:查找存储在hashMap中的对象的最佳性能方法 - JAVA : Best performance-wise method to find an object stored in hashMap 在性能/加载时间上哪个更好? (Java字符串) - Which would be better performance/loading time wise? (Java strings) java Integer 的 ConcurrentHashMap 与 AtomicInteger 的 HashMap 与 AtomicInteger 的 ConcurrentHashMap - java ConcurrentHashMap of Integer vs HashMap of AtomicInteger vs ConcurrentHashMap of AtomicInteger HashMap 到 concurrentHashMap - HashMap to concurrentHashMap
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM