Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ConcurrentHashMap在性能方面优于HashMap?_Java_Performance_Data Structures_Concurrency_Hashmap - Fatal编程技术网

Java ConcurrentHashMap在性能方面优于HashMap?

Java ConcurrentHashMap在性能方面优于HashMap?,java,performance,data-structures,concurrency,hashmap,Java,Performance,Data Structures,Concurrency,Hashmap,我刚读了《清洁代码》一书,偶然发现了这样一句话: Java年轻时,Doug Lea写了一本开创性的书[8] 用Java编程。除了这本书之外,他还写了几本 线程安全集合,该集合后来成为 java.util.concurrent包。该包中的集合是安全的 对于多线程情况,它们的性能很好事实上 ConcurrentHashMap实现的性能优于HashMap 几乎所有的情况。它还允许同时进行并发操作 读取和写入,并且它具有支持公共组合的方法 否则不是线程安全的操作。如果Java5是 部署环境,从 Conc

我刚读了《清洁代码》一书,偶然发现了这样一句话:

Java年轻时,Doug Lea写了一本开创性的书[8] 用Java编程。除了这本书之外,他还写了几本 线程安全集合,该集合后来成为
java.util.concurrent
包。该包中的集合是安全的 对于多线程情况,它们的性能很好事实上
ConcurrentHashMap
实现的性能优于HashMap
几乎所有的情况。它还允许同时进行并发操作 读取和写入,并且它具有支持公共组合的方法 否则不是线程安全的操作。如果Java5是 部署环境,从
ConcurrentHashMap

请注意,在上面的引用中,我使用了“[n]”,其中n是一些数字,以表示作者提供参考的地方,正如您所看到的,他没有提供任何粗体部分的参考

并不是说我不相信这句话,而是我想知道这句话的支持证据。那么,有人知道显示
ConcurrentHashMap
HashMap
性能统计信息的资源吗?或者有人能向我解释为什么ConcurrentHashMap比HashMap快


在休息的时候,我可能会研究ConcurrentHashMap在工作中的实现,但现在我想听听其他SOER的答案

这是一种很难用一种或另一种方式证明的有弹性的陈述。在“几乎所有情况”下,你如何衡量某件事

ConcurrentHashMap
可能比同步的
HashMap
更好。争论越多,差别就越大。另一方面,非同步的
HashMap
可能比
ConcurrentHashMap
更快,因为后者会带来不必要的锁定开销



我还想看看这句话的来龙去脉,以及这本书的作者提出了什么证据来支持它。还有未说明的假设的证据,即哈希映射的“几乎所有”用例都涉及同步。

如果您仅使用单线程哈希映射访问哈希映射,则最快(它不进行任何同步),如果您是从多个线程访问它,那么ConcurrentHashMap比手工粗粒度同步要快。请参见此处进行比较:


道格·李在这些方面非常擅长,因此如果他的
ConcurrentHashMap
曾经比约书亚·布洛赫的
HashMap
表现更好,我也不会感到惊讶。然而,从Java7开始,
HashMap
的第一位@author也成为了DougLea。显然现在没有理由
HashMap
会比它的并发表慢

出于好奇,我做了一些基准测试。我在Java7下运行它。条目越多,性能越接近。最终,
ConcurrentHashMap
HashMap
的比例在3%以内,这是非常显著的。瓶颈实际上是内存访问,俗话说,“内存就是新磁盘(磁盘就是新磁带)”。如果条目在缓存中,两个条目都将是快速的;如果条目不适合缓存,则两者都会变慢。在实际应用程序中,地图不必太大,就可以与其他地图竞争是否驻留在缓存中。如果经常使用地图,它会被缓存;如果不是,它就不会被缓存,这才是真正的决定因素,而不是实现(假设两者都是由同一位专家实现的)

publicstaticvoidmain(字符串[]args)
{

对于(int i=0;iHashMap可能较慢的原因是,它必须检测ConcurrentModification才能知道何时引发异常。ConcurrentHashMap不必检查modCount以知道何时引发异常(但它确实将其用于size()和isEmpty())。获取锁非常快,尤其是在单线程情况下,当您已经持有锁时,但是检查modCount是两次读取,如果不等于HashMap必须支付抛出CoModException的费用,则跳转


我建议您阅读collections类的源代码,这样您就可以知道它们在进行方法调用时所做的工作。在只有字典get/put的完全私有映射的情况下,您通常可以使用精简的HashMap,而无需任何modCount,甚至无需进行大小跟踪,以提高性能。

在上下文中,很难说出作者的意思,但也许作者的意思是坚持“同步”所有HashMap方法都是一个坏主意,使用明确设计的支持多线程的东西,比如ConcurrentHashMap,是一个更好的主意。我在干净的代码中找不到这句话,但它是一本大书…@Matthew,它在183页,页面顶部。它是第13章并发性。@Jeff Foster不是真的,它只是说开始使用ConcurrentHashMap而不是HashMap。我用确切的段落更新了我的问题。如果使用Collections.synchronizedMap(HashMap),您将得到一个作为整个实体锁定的映射。ConcurrentHashMap允许一些并发访问(读写),方法是将锁条带化,以便将哈希表划分为独立锁定的域。@Alvin-我对上下文的理解是引用的语句实际上是指多线程应用程序。前一句是赠品。在这种上下文中,我不会不同意。@StephenC前一句说它对于多线程的情况是安全的,而且它们的性能很好,而有争议的一个说几乎所有的情况-所以我怀疑上下文的范围只是多线程应用程序。我想我仍然同意你最初的评论-证据在哪里?但是作者似乎建议使用ConcurrentHa
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.
}