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