23

我想知道构造 a 的参数ConcurrentHashMap

  • initialCapacity默认为 16(可以理解)。
  • loadFactor默认为 0.75。
  • concurrencyLevel默认为 16。

我的问题是:

  • 应该使用什么标准来loadFactor向上或向下调整?
  • 我们如何确定并发更新线程的数量?
  • 应该使用什么标准来concurrencyLevel向上或向下调整?

此外:

  • 一个好的哈希码实现的标志是什么?(如果一个 SO 问题解决了这个问题,只需链接到它。)

谢谢!

4

4 回答 4

19

简短的回答:将“初始容量”设置为您希望在地图中放置多少映射,并将其他参数保留为默认值。

长答案:

  • 负载因子是地图中“桶”数与预期元素数之比;

  • 0.75 通常是一个合理的折衷——我记得,这意味着对于一个好的散列函数,我们平均期望大约 1.6 次重定向来找到地图中的一个元素(或该图周围);

    • 改变负载因子改变了更多重定向之间的折衷以找到一个元素但更少浪费空间——放 0.75 通常是一个很好的值;

    • 原则上,将 ConcurrencyLevel 设置为您希望修改映射的并发线程数,尽管高估这似乎不会产生除了浪费内存之外的坏影响(我不久前写了一点关于ConcurrentHashMap 性能 的文章,以防你'重新感兴趣)

非正式地,您的散列函数本质上应该旨在尽可能多地具有“随机性”。或者更严格地说,给定元素的哈希码应该让每个位有大约 50% 的机会被设置。用一个例子来说明这一点实际上更容易:同样,你可能对我写的关于字符串散列函数如何工作和相关散列函数指南的一些东西感兴趣。任何这些东西都欢迎反馈。

我在某些时候还提到的一件事是,您不必在实践中过于偏执:如果您的哈希函数在某些位中产生“合理”数量的随机性,那么它通常是可以的。在最坏的情况下,将具有代表性的数据片段粘贴到字符串中并获取字符串的哈希码实际上并没有那么糟糕。

于 2009-10-15T17:49:12.647 回答
4

负载因子主要与散列函数的质量有关。负载因子越接近零,即使散列函数不是那么大,发生冲突的可能性就越小。权衡是内存占用更大。换句话说,HashMap 并没有为每个单独的哈希码分配单独的桶中的条目,而是按接近度对它们进行分组,因此它拥有的桶越多,分布越分散,发生冲突的可能性就越小。

因此,底线是您根据您的需要和存储在 Map 中的对象来调整负载因子以改善查找时间或减少内存。

ConcurrencyLevel 实际上取决于您的应用程序。如果应用程序中只有两个或三个线程在运行,那么就可以了。如果您是具有任意数量线程的应用程序服务器,那么您需要了解您的负载能力是什么以及您想要优化的点。

一个高质量的哈希码实现提供了尽可能广泛的对象潜在值的分布,碰撞次数最少,同时遵守合同。换句话说,它允许 HashMap(或 Set 视情况而定)将对象分布到单独的桶中,​​从而加快查找速度。

于 2009-10-15T17:47:44.397 回答
0

loadFactor:控制实现何时决定调整哈希表的大小。值太高会浪费空间;值太低会导致代价高昂的调整大小操作。

concurrencyLevel:告诉实现尝试针对给定数量的写入线程进行优化。根据 API 文档,最多降低 10 倍不应该对性能产生太大影响。

更新操作之间允许的并发性由可选的 concurrencyLevel 构造函数参数(默认为 16)指导,该参数用作内部大小调整的提示。该表在内部进行了分区,以尝试允许指定数量的并发更新而不会发生争用。因为哈希表中的放置本质上是随机的,所以实际的并发性会有所不同。理想情况下,您应该选择一个值来容纳尽可能多的线程同时修改表。使用显着高于您需要的值会浪费空间和时间,而显着降低的值会导致线程争用。但是一个数量级内的高估和低估通常不会产生太大的影响。

一个好的散列码实现将散列值均匀地分布在任何间隔上。如果事先知道一组键,则可以定义一个“完美”的散列函数,为每个键创建一个唯一的散列值。

于 2009-10-15T17:37:39.093 回答
0

loadFactor 默认设置为 0.75,应该使用什么标准来向上或向下调整?

在了解哈希映射的工作原理之前,您需要一些背景知识。地图本质上是一系列桶。映射中的每个值都根据其哈希码放入存储桶中。loadFactor 的意思是,如果桶超过 75% 满,地图应该调整大小

concurrencyLevel 默认设置为 16,我们如何确定并发更新线程的数量?应该使用什么标准来向上或向下调整?

这是询问您希望同时(同时)修改 Map 的线程数

有关哈希码,请参阅 Joshua Bloch 的Effective Java

于 2009-10-15T17:37:39.217 回答