Mau*_*uli 63 java collections hashmap
如何将ConcurrentHashMap的性能与HashMap进行比较,特别是.get()操作(我特别感兴趣的是只有少数几个项目的情况,范围可能在0-5000之间)?
有没有理由不使用ConcurrentHashMap而不是HashMap?
(我知道不允许使用空值)
更新
只是为了澄清,显然在实际并发访问的情况下性能会受到影响,但是如何在没有并发访问的情况下比较性能呢?
Bil*_*ell 86
线程安全是一个复杂的问题.如果您想使对象线程安全,请有意识地做,并记录该选择.使用你的类的人会感谢你,如果它是简单的使用它是线程安全的,但如果一个曾经是线程安全的对象在未来的版本中变得不那样,他们会诅咒你.线程安全虽然非常好,但不仅仅是圣诞节!
现在问你的问题:
ConcurrentHashMap(至少在Sun的当前实现中)通过将底层映射划分为多个单独的桶来工作.获取元素本身不需要任何锁定,但它确实使用原子/易失性操作,这意味着存储器障碍(可能非常昂贵,并且干扰其他可能的优化).
即使JIT编译器在单线程情况下可以消除原子操作的所有开销,仍然存在确定要查看哪个桶的开销 - 不可否认这是一个相对快速的计算,但是,它仍然是不可能消除.
至于决定使用哪种实现,选择可能很简单.
如果这是一个静态字段,你几乎肯定想要使用ConcurrentHashMap,除非测试显示这是一个真正的性能杀手.您的类具有与该类实例不同的线程安全期望.
如果这是一个局部变量,那么HashMap就足够了 - 除非您知道对该对象的引用可能泄漏到另一个线程.通过编码到Map界面,如果发现问题,您可以在以后轻松更改它.
如果这是一个实例字段,并且该类尚未设计为线程安全的,则将其记录为不是线程安全的,并使用HashMap.
如果您知道此实例字段是该类不是线程安全的唯一原因,并且愿意接受有前途的线程安全所暗示的限制,那么请使用ConcurrentHashMap,除非测试显示出显着的性能影响.在这种情况下,您可以考虑允许类的用户以某种方式选择对象的线程安全版本,可能使用不同的工厂方法.
在任何一种情况下,将类记录为线程安全(或有条件地线程安全),因此使用您的类的人知道他们可以跨多个线程使用对象,编辑您的类的人知道他们必须在将来保持线程安全.
Ata*_*ais 66
我真的很惊讶地发现这个话题太老了,但还没有人提供任何关于这个案例的测试.使用ScalaMeter我创建的测试add,get并remove为双方HashMap并ConcurrentHashMap在两种情况下:
HashMap它不是线程安全的,我只是HashMap为每个线程创建了单独的,但是使用了一个,共享ConcurrentHashMap.代码可以在我的仓库中找到.
如果要尽快操作数据,请使用所有可用线程.这似乎是显而易见的,每个线程都有完成工作的1/n.
如果您选择单线程访问使用HashMap,它会更快.对于add方法来说,效率甚至高达3倍.只有get更快ConcurrentHashMap,但不多.
当ConcurrentHashMap使用多个线程进行操作时,HashMaps对于每个线程单独操作同样有效.因此,不需要在不同的结构中对数据进行分区.
总而言之,ConcurrentHashMap当您使用单线程时,性能会更差,但添加更多线程来完成工作肯定会加快进程.
测试平台
AMD FX6100,16GB Ram
Xubuntu 16.04,Oracle JDK 8更新91,Scala 2.11.8
| 归档时间: |
|
| 查看次数: |
49896 次 |
| 最近记录: |