问题标签 [concurrenthashmap]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
1300 浏览

java - 如何正确使用并发哈希图?

比如说,我有很多读取操作和一些写入操作,并且将放置在 map 中的对象非常“重” - 初始化此类对象会花费大量内存/时间等。

我应该如何编码以既利用并发哈希图的高性能又确保对那些缓存对象进行不必要的初始化的成本最低。

欢迎使用示例代码片段,非常感谢!谢谢!

0 投票
1 回答
3014 浏览

java - ConcurrentHashMap 的实现和限制

我有一个相当大的项目要完成,我遇到了一些死胡同。我想看看这里的伟大社区是否有任何建议。

我有一个大数据集,我正在尝试构建一个社交图。该数据包含超过 950 万个坐标到 Short 值的映射。对于 ConcurrentHashMap 中的键值,我使用的是字符串,即在其间用 ',' 连接的坐标。

本质上,我正在查找用户之间共有的组数。我有一个非常容易构建的初始哈希图,它将 GroupID 映射到 AvatarID 的向量。这部分运行良好。然后,我有 12 个线程负责他们自己的 GroupID 集和处理(将每个 groupID 中用户之间的计数加 + 1),所有访问都从 ConcurrentHashMap 完成。

在处理了大约 8000 个组后,出现访问问题。一次似乎只有一个线程处于活动状态,我不确定这是因为尺寸过大还是其他因素。这是一个问题,因为我总共需要处理 300,000 个组(并且要及时处理)。

关于我如何实现这一点以及我可以使用的任何快捷方式有什么建议吗?我认为读写同样重要,因为如果值存在(如果不创建它),我必须读取坐标,然后将值加一并写回。

我愿意根据需要提供代码,我只是不知道哪些部分与讨论相关。

谢谢你的时间,-mojavestorm

进一步说明:

两种实现及其限制:

1) 我有一个 HashMap(Integer, Vector(Integer)) preMap,其中包含一个 GroupID 作为键和一个用户 ID 向量。线程在彼此之间拆分 GroupID,并使用返回的每个 Vector(Integer),每个线程根据坐标(即 UserID x 和 UserID y 一起属于(短)n 个组)将一个短值存储到一个 TLongShortHashMap threadMap 中,并且每个线程都拥有自己的线程映射。坐标映射到长值。每个线程完成后,将每个threadMap中对应key的值添加到combinedMap中的同一个key中,这将显示整个系统中有多少组UserID x和UserID y一起属于。

这个实现的问题是线程之间有很高的重叠,所以创建了过多的短值。例如,用户 1 和用户 2 一起属于不同的组。线程 A 和线程 B 负责他们自己的组范围,包括用户 1 和用户 2 所属的组,因此线程 A 和线程 B 都在他们的 threadMap 副本中存储坐标 (1, 2) 的长值和一个短值。如果发生过多重叠,则内存需求可能会很突出。就我而言,我分配给 Java 的所有 46GB 内存都用完了,而且速度也很快。

2)在这个实现中使用相同的preMap,每个线程都被赋予了他们负责的用户坐标范围。每个线程运行,并获取它拥有的每个坐标并遍历 preMap,检查每个 groupID 并查看 UserID x 和 UserID y 是否属于从 preMap 返回的向量。此实现消除了线程映射之间将发生的重叠。

这个问题是时间。目前,该计划正以惊人的速度运行,需要 1400 年才能完成。使用的内存在 4GB 到 15GB 左右波动,但似乎保持“低”。不完全确定它会保持在限制范围内,但是,我想它会。对我来说没有明显的改进。

希望这些描述清楚,有助于深入了解我的问题。谢谢。

0 投票
3 回答
648 浏览

java - 使用并发哈希图来减少线程池的内存使用?

我正在使用一个运行冗长的 SQL 查询并将处理后的结果存储在 HashMap 中的程序。目前,为了解决每个 20-200 个查询的缓慢执行时间,我使用一个固定的线程池和一个自定义的可调用来进行搜索。因此,每个可调用对象都会创建数据的本地副本,然后将其返回到主程序以包含在报告中。

我注意到过去运行没有问题的 100 个查询报告现在导致我内存不足。我的猜测是,因为这些可调用对象正在创建自己的数据副本,所以当我将它们加入另一个大型 HashMap 时,内存使用量会增加一倍。我意识到我可以尝试通过减小可调用表的范围来哄垃圾收集器运行,但是如果可以避免的话,这种级别的重组并不是我真正想要做的。

我可以通过将可调用对象替换为可运行对象而不是存储数据,而是将其写入并发 HashMap 来提高内存使用率吗?还是听起来我这里有其他问题?

0 投票
1 回答
10521 浏览

c++ - TBB 并发哈希图

我正在实现 tbb 的并发哈希映射,以将它的性能与一组其他并发哈希表进行比较。

但是我从中得到的性能是可怕的,我简直不敢相信它与其他并发哈希表相比有那么慢

这是我的实现:

有没有人看到我的实现有任何问题,或者知道它执行缓慢的任何原因?在单线程环境中插入 200,000 个元素需要 30 多分钟。从这个角度来看,几乎所有其他表都在不到 5 分钟的时间内完成了这个测试。

这是我的构建代码:

更新:我已调整我的测试代码以将哈希表预填充为 1000,而不是 100,000。再次运行时,tbb 执行 92 op/sec,而另一个实现执行 89431 op/sec。(64线程环境)...只是说什么似乎不对....

附加信息:计算机是具有 6gb 内存和 6 个内核的 HP Z600 工作站。

注意交叉定位:http ://software.intel.com/en-us/forums/showthread.php?t=86119

0 投票
0 回答
614 浏览

java - @Singleton 缓存实现

我想知道我的缓存实现是否正确,并希望得到任何反馈。资源分配了一些字符串(客户端地址)值。

我必须同步 addEntityRegistration() 方法吗?或者这个用例有更好的方法吗?

在此先感谢,米

0 投票
2 回答
2943 浏览

java - ConcurrentHashMap foreach 循环问题

我有一个名为 users 的并发哈希图。我在其中有一些用户对象,其中包含一些不是 id 的整数键。我想找到具有给定 ID 的用户。因此,我检查 hashmap 的所有元素并返回用户对象(如果存在)。这是我的代码:

然而,即使我的 u.getId() 和 id 是相同的,我也无法在我的日志中看到“匹配”。

213 匹配但不能输入下面的 if 语句。这是我的日志:

在此处输入图像描述

你怎么看待这件事?

0 投票
6 回答
3588 浏览

java - 将对象重新放入 ConcurrentHashMap 是否会导致“先发生”内存关系?

我正在使用具有 ConcurrentHashMap 形式的对象存储的现有代码。映射中存储了可变对象,供多个线程使用。没有两个线程试图通过设计一次修改一个对象。我担心的是线程之间修改的可见性。

目前,对象的代码在“setter”(由对象本身保护)上具有同步。“getter”上没有同步,成员也不是易变的。对我来说,这意味着无法保证可见性。但是,当一个对象被修改时,它会重新放回映射put()中(再次调用该方法,相同的键)。这是否意味着当另一个线程将对象拉出映射时,它会看到修改?

我在 stackoverflow、JCIP和 java.util.concurrent 的包描述中对此进行了研究。我想我基本上把自己弄糊涂了……但让我问这个问题的最后一根稻草来自包装描述,它指出:

在将对象放入任何并发集合之前线程中的操作发生在另一个线程中从集合中访问或删除该元素之后的操作。

关于我的问题,“动作”是否包括在 re-put() 之前对存储在地图中的对象的修改?如果所有这些确实导致跨线程的可见性,这是​​一种有效的方法吗?我对线程比较陌生,非常感谢您的评论。

编辑:

谢谢大家的回复!这是我在 StackOverflow 上的第一个问题,对我很有帮助。

我必须接受ptomli的回答,因为我认为它最清楚地解决了我的困惑。也就是说,在这种情况下,建立“之前发生”关系并不一定会影响修改可见性。关于文本中描述的实际问题,我的“标题问题”构造不佳。ptomli的回答现在与我在JCIP中读到的内容不谋而合:“为确保所有线程都能看到共享可变变量的最新值,读写线程必须在公共锁上同步”(第 37 页)。将对象重新放入映射中不会为修改插入对象的成员提供这种通用锁。

我很欣赏所有改变的技巧(不可变对象等),我完全同意。但是对于这种情况,正如我提到的,由于仔细的线程处理,没有并发修改。一个线程修改一个对象,另一个线程稍后读取该对象(CHM 是对象传送器)。鉴于我提供的情况,我认为 CHM 不足以确保稍后执行的线程将看到第一个的修改。但是,我认为你们中的许多人正确回答了标题问题

0 投票
1 回答
2516 浏览

java - ConcurrentHashMap 非阻塞读取和内存可见性问题

ConcurrentHashMap在 Java 中提供读取以与更新同时进行。这样做的权衡是读取的结果仅限于反映读取开始时最后完成的更新,因此未指定反映元素的最新状态。

但是 AFAIK Java 内存模型,如果在读写线程之间没有某种形式的同步,即使经过任意时间,写线程的更新也可能对读线程不可见。

鉴于读取线程不会与写入线程阻塞,那么保证读取线程可用的最后完成更新的可见性的基础是什么?

我只能想到比较和交换算法在起作用,但我无法在该库的源代码中验证它。

0 投票
1 回答
161 浏览

java - Java tomcat如何仅将某些http Thread排队?

我有一个无状态 Java 应用程序部署到一个 tomcat Web 服务器。由于数据的性质,在任何给定时间,所有 http 线程都必须处理不同的密钥(换句话说:所有线程必须处理不同的密钥)。

因此,我编写了一个模块,如果请求的键是当前正在进行的(在此之前的 http 帖子),则将 http 帖子排队。只有在上一个具有相同密钥的 http 帖子完成其处理后,我才会继续处理当前的 http 帖子。

我用 concurrenthashmap 写了一个简单的 while 循环来测试是否有任何先前的请求在进行中。性能低于标准,并且存在意外行为。这是代码片段:

在每个 http 帖子的最后,在 finally 块中,我输入: transQueue.remove(queueKey) 以确保我已将其从并发哈希图中删除。然而,在我最糟糕的噩梦中,从服务器日志中,我注意到在我删除 queueKey 之前,另一个 http post 线程设法摆脱了上面的 while 循环并继续处理。

我在上面的代码中做错了什么来“排队”http线程吗?

也非常感谢任何关于我如何能更好地做到这一点的想法。

0 投票
2 回答
1257 浏览

java - ConcurrentNavigableMap,弱一致迭代器的解释

ConcurrentNavigableMap 的 JavaDoc 中,我对以下内容有些困惑:

视图的迭代器是一个“弱一致”的迭代器,它永远不会抛出 ConcurrentModificationException,并保证在构造迭代器时遍历元素,并且可以(但不保证)反映构造后的任何修改。

在 ConcurrentSkipListMap 等接口的实现中,措辞似乎相同。

这是什么意思,这似乎是一个矛盾 - 要么它可以保证遍历元素,因为它们存在于构造中,或者它可能反映构造后的修改?

更新:我基本上想知道是否在 ConcurrentNavigableMaps 上创建迭代器,如 ConcurrentSkipListMap,创建地图的“快照”视图。