我想知道构建ConcurrentHashMap
的参数:
initialCapacity
默认为16(理解)。loadFactor
默认为0.75。concurrencyLevel
默认为16。我的问题是:
loadFactor
上升或下降?concurrencyLevel
上升或下降?此外:
谢谢!
答案 0 :(得分:17)
简短回答:将“初始容量”设置为大致希望在地图中放置多少映射,并将其他参数保留为默认值。
答案很长:
负载系数是指之间的比例 地图中的“桶”数量 预期要素的数量;
0.75通常是一个合理的妥协 - 我记得,这意味着用一个 良好的哈希函数,平均而言我们 期待大约1.6重定向找到一个 地图中的元素(或该图周围);
更改负载 因素改变了之间的妥协 更多重定向来查找元素但是 减少浪费空间 - 放0.75 通常是一个很好的价值;
原则上,将ConcurrencyLevel设置为 你并发线程的数量 期待修改地图, 虽然过高估计这一点并非如此 其他似乎有不好的影响 而不是浪费记忆(我写了一点 在ConcurrentHashMap performance 不久之前万一你是 感兴趣的)
非正式地,您的哈希函数本质上应该旨在尽可能多地在比特中“随机”。或者更严格地说,给定元素的哈希码应该给每个位大约50%的机会设置。实际上用一个例子来说明这一点实际上更容易:再次,您可能对我撰写的关于how the String hash function works和相关hash function guidelines的一些内容感兴趣。对这些内容的反馈是显而易见的欢迎。
我在某些方面也提到的一件事是你在实践中不必过于偏执:如果你的哈希函数在某些位中产生“合理”的随机性,然后通常会好的。在最糟糕的情况下,将代表性的数据片段粘贴到字符串中并获取字符串的哈希码实际上并不是那么糟糕。
答案 1 :(得分:4)
负载因子主要与散列函数的质量有关。负载因子越接近零,即使散列函数不那么大,碰撞的可能性也越小。权衡是内存占用更大。换句话说,HashMap不是为每个单独的哈希码在单独的桶中分配条目,而是按接近度对它们进行分组,因此它拥有的桶越多,分布越分散,冲突的可能性就越小。
所以最重要的是你根据你的需要和你在地图中存储的对象来调整加载因子以改善查找时间或减少内存。
ConcurrencyLevel实际上取决于您的应用程序。如果您只在应用程序中运行了两个或三个线程,那么就去了。如果您是具有任意数量线程的应用程序服务器,那么您需要了解您的负载容量以及要优化的点。
优质的哈希码实现在尽可能少的冲突的同时提供尽可能广泛的对象潜在值的分布,同时遵守合同。换句话说,它允许HashMap(或者视情况而定)将对象分配到单独的桶中,使查找更快。
答案 2 :(得分:0)
loadFactor:控制实现何时决定调整哈希表的大小。价值太高会浪费空间;太低的值会导致昂贵的调整大小操作。
concurrencyLevel:告诉实现尝试针对给定数量的写入线程进行优化。根据API文档,最多关闭10倍不会对性能产生太大影响。
更新中允许的并发性 操作由可选项指导 concurrencyLevel构造函数参数 (默认值为16),用作提示 用于内部尺寸。表是 内部分区尝试 允许指定的数量 没有争用的并发更新。 因为哈希表中的位置是 基本上是随机的,实际的 并发性会有所不同。理想情况下,你 应该选择一个值来容纳 尽可能多的线程 同时修改表。用一个 价值显着高于你 需要可以浪费空间和时间,和 价值显着降低可导致 线程争用。但是高估了 并且低估了 幅度通常不大 明显的影响。
良好的哈希码实现将在任何时间间隔内均匀分布哈希值。如果事先知道了这组键,则可以定义一个“完美”哈希函数,为每个键创建一个唯一的哈希值。
答案 3 :(得分:0)
默认情况下,loadFactor设置为0.75 应该用什么标准来调整 这个上升还是下降?
您需要了解哈希映射的工作方式,然后才能了解其工作原理。地图本质上是一系列的桶。地图中的每个值都会根据其哈希码的内容放入存储桶中。 loadFactor意味着,如果存储桶已满75%,则应调整地图的大小
concurrencyLevel设置为16 默认情况下,我们如何建立 并发更新的次数 线程?应该使用什么标准 向上还是向下调整?
这是在询问您期望多少线程同时(同时)修改Map
对于哈希码,请参阅Joshua Bloch的Effective Java