gpt4 book ai didi

Java ConcurrentHashMap 损坏的值

转载 作者:塔克拉玛干 更新时间:2023-11-02 07:53:15 25 4
gpt4 key购买 nike

我有一个 ConcurrentHashMap,它有时会表现出奇怪的行为。

当我的应用首次启动时,我从文件系统中读取一个目录,并使用文件名作为键将每个文件的内容加载到 ConcurrentHashMap 中。有些文件可能是空的,在这种情况下我将值设置为“空”。

加载完所有文件后,工作线程池将等待外部请求。当收到请求时,我调用 getData() 函数来检查 ConcurrentHashMap 是否包含 key 。如果 key 存在,我将获取该值并检查该值是否为“空”。如果 value.contains("empty"),我返回“找不到文件”。否则,返回文件的内容。当 key 不存在时,我尝试从文件系统加载文件。

private String getData(String name) {
String reply = null;
if (map.containsKey(name)) {
reply = map.get(name);
} else {
reply = getDataFromFileSystem(name);
}

if (reply != null && !reply.contains("empty")) {
return reply;
}

return "file not found";
}

有时,ConcurrentHashMap 将返回非空文件的内容(即 value.contains("empty") == false),但是行:

if (reply != null && !reply.contains("empty")) 

返回假。我将 IF 语句分解为两部分:if (reply != null)if (!reply.contains("empty"))。 IF 语句的第一部分返回 TRUE。第二部分返回 FALSE。所以我决定打印出变量“reply”以确定字符串的内容是否确实包含“empty”。情况并非如此,即内容不包含字符串“空”。此外,我添加了行

int indexOf = reply.indexOf("empty");

因为当我打印出来时变量 reply 不包含字符串“empty”,所以我期望 indexOf 返回 -1。但是该函数返回的值大约是字符串的长度,即 如果 reply.length == 15100,则 reply.indexOf("empty") 返回 15099。

我每周都会遇到这个问题,大约每周 2-3 次。此进程每天重新启动,因此会定期重新生成 ConcurrentHashMap。

有没有人在使用 Java 的 ConcurrentHashMap 时看到过这种行为?

编辑

private String getDataFromFileSystem(String name) {
String contents = "empty";
try {
File folder = new File(dir);

File[] fileList = folder.listFiles();
for (int i = 0; i < fileList.length; i++) {
if (fileList[i].isFile() && fileList[i].getName().contains(name)) {
String fileName = fileList[i].getAbsolutePath();

FileReader fr = null;
BufferedReader br = null;

try {
fr = new FileReader(fileName);
br = new BufferedReader(fr);
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
contents += sCurrentLine.trim();
}
if (contents.equals("")) {
contents = "empty";
}

return contents;
} catch (Exception e) {
e.printStackTrace();

if (contents.equals("")) {
contents = "empty";
}
return contents;
} finally {
if (fr != null) {
try {
fr.close();
} catch (Exception e) {
e.printStackTrace();
}
}

if (br != null) {
try {
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}

if (map.containsKey(name)) {
map.remove(name);
}

map.put(name, contents);
}
}
}
} catch (Exception e) {
e.printStackTrace();

if (contents.equals("")) {
contents = "empty";
}
return contents;
}
return contents;
}

最佳答案

我认为你的问题是你的一些操作应该是原子的,但它们不是。

例如,一种可能的线程交错场景如下:

  • 线程 1 在 getData 方法中读取这一行:

    if (map.containsKey(name)) // (1)
  • 结果为假,线程1转到

    reply = getDataFromFileSystem(name); // (2)
  • getDataFromFileSystem 中,您有以下代码:

    if (map.containsKey(name)) { // (3)
    map.remove(name); // (4)
    }
    map.put(name, contents); // (5)
  • 假设另一个线程(线程 2)到达 (1),而线程 1 在 (4)(5) 之间: name 不在 map 中,所以线程 2 再次转到 (2)

现在这并不能解释您所观察到的具体问题,但它说明了一个事实,即当您让许多线程在一段没有同步的代码中并发运行时,奇怪的事情可能而且确实会发生。

就目前而言,我找不到对您描述的场景的解释,除非您在测试中多次调用 reply = map.get(name),在这种情况下这 2 个调用很可能不会返回相同的结果。

关于Java ConcurrentHashMap 损坏的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11401197/

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