gpt4 book ai didi

java - 使用 putIfAbsent 重叠 ConcurrentHashMap put

转载 作者:太空宇宙 更新时间:2023-11-04 06:56:30 26 4
gpt4 key购买 nike

插入哈希表时似乎存在问题。我创建了大约 8 个线程,并在每个线程中执行以下代码。每个线程接收一个 char[] 数组。每个线程的工作是标记该数组(查找空格)。找到 token 后,如果不存在,我需要将其添加到哈希表中。如果它确实存在,那么我需要将该 token ( key )的当前值加 1。

您可能会问的问题:

为什么不从 char[] 转换为 String?

我尝试了这个,由于字符串是不可变的,我最终耗尽了内存(我正在处理一个 10g 文件),或者我花了太长时间进行垃圾收集。使用Character[],我可以重用相同的变量,并且不会占用额外的内存空间。

问题是什么?

处理完整个文件后,我运行代码:

for (Entry<Character [], Integer> e : wordCountMap.entrySet()) {
System.out.println(Arrays.toString(e.getKey()) + " = " + e.getValue());
}

在我的主要功能中。我得到的结果是少于 100 个键/值对。我知道应该有2万左右。不知怎的,似乎有一些重叠。

    Character [] charArray = new Character[8];
for (i = 0; i < newbyte.length; i++) { //newbyte is a char[] from main
if (newbyte[i] != ' ') {
charArray[counter] = newbyte[i];
counter++;
}
else {
check = wordCountMap.putIfAbsent(charArray, 1);
if (check != null) {
wordCountMap.put(charArray, wordCountMap.get(charArray) + 1);
}
for (j = 0; j < counter; j++) {
charArray[j] = null;
}//Null out the array

ConcurrentMap<Character [], Integer> wordCountMap //this is the definition in main

正如下面的一些评论所建议的,我实际上是在以下行时传递对 charArray 的引用:

wordCountMap.put(charArray, wordCountMap.get(charArray) + 1);

被执行。所以我的问题是,如何传递值?现在实际上非常有意义,因为最终大约有 320 个键/值对 - 8 个线程,40 个循环(每个线程每次迭代获得 250/8 MB)。

最佳答案

我认为如果不同步 get() 和 put() 操作,这是不可能实现的。

根据ConcurrentHashMap docs

Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations holding upon their onset.

这意味着如果您的两个线程同时遇到相同的计数器,则 get() 将返回相同的值(例如 2 ),并且它们都将插入 2+1=3。因此,代币的数量将被低估 - 即是 3 个而不是 4 个。

为了保持一致,需要在get()操作之前进行同步,这会大大降低多线程的好处。

如果您愿意,您可以这样做:

class Key {
char[] buffer = new char[8];
Key copy() {
Key copy = new Key();
for ( int i =0; i < 8; i++) {
copy.buffer[i] = this.buffer[i];
}
}
public int hashCode() {
return Arrays.hashCode(buffer);
}
public boolean equals(Object obj) {
if ( obj instanceof Key) {
return Arrays.equals(((Key) obj).buffer, this.buffer);
}
return false;
}
}
//YOur code modified:
Key checker = new Key();
for (i = 0; i < newbyte.length; i++) { //newbyte is a char[] from main
if (newbyte[i] != ' ') {
checker.buffer[counter] = newbyte[i];
counter++;
}
else {
synchronized (wordCountMap) {
Integer value = workCountMap.get(checker);
if ( value == null ) {
workCountMap.put(checker.copy(), 1);
} else {
wordCountMap.put(checker.copy(), value + 1);
}
}
for (j = 0; j < counter; j++) {
checker.buffer[j] = null;
}//Null out the array
}

这将解决您的内存问题,因为仅当您必须插入表时才执行new()(通过copy())。因此,使用的内存是您需要的最小值(不计算 i、j、检查器等)。然而,你会失去几乎所有的并行性。

如果我是你,我会将文件分解为多个片段,并在单独的线程中处理每个片段。每个线程都可以维护自己的 HashMap 。在整个文件的末尾,您将有 n 个哈希表(n 是线程数)。然后您可以合并 n 个 HashMap 。所需的内存将是之前 HashMap 大小的 n 倍。

如果您想了解有关此方法的更多详细信息,请告诉我,我会尽力提供帮助。

关于java - 使用 putIfAbsent 重叠 ConcurrentHashMap put,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22674497/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com