【发布时间】:2012-07-09 18:49:31
【问题描述】:
我有一个 ConcurrentHashMap,它有时会表现出奇怪的行为。
当我的应用程序第一次启动时,我从文件系统中读取一个目录,并使用文件名作为键将每个文件的内容加载到 ConcurrentHashMap 中。有些文件可能是空的,在这种情况下,我将值设置为“空”。
加载所有文件后,工作线程池将等待外部请求。当一个请求进来时,我调用 getData() 函数来检查 ConcurrentHashMap 是否包含密钥。如果密钥存在,我将获取值并检查该值是否为“空”。如果 value.contains("empty"),我返回 "file not found"。否则,返回文件的内容。当密钥不存在时,我尝试从文件系统加载文件。
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"))
返回 FALSE。我将 IF 语句分为两部分:if (reply != null) 和 if (!reply.contains("empty"))。 IF 语句的第一部分返回 TRUE。第二部分返回 FALSE。所以我决定打印出变量“reply”,以确定字符串的内容是否确实包含“空”。情况并非如此,即内容不包含字符串“empty”。此外,我添加了行
int indexOf = reply.indexOf("empty");
由于我打印出来的变量reply 不包含字符串“empty”,我期待indexOf 返回-1。但是该函数返回了一个近似于字符串长度的值,即if 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;
}
【问题讨论】:
-
我根本不相信
foo.indexOf("empty")会永远为非空字符串返回foo.length() - 1。这意味着String.indexOf非常糟糕。我不相信ConcurrentHashMap或String坏了 - 我强烈怀疑你的代码在某个地方坏了。 -
你能显示
getDataFromFileSystem(name);的代码吗? -
那是 actual getData() 方法,还是您将其重新编写到此处发布?
-
actual getData() 方法具有额外的日志记录,已在本文中删除。
-
我将在下面的帖子中定义函数 getDataFromFileSystem(name);...
标签: java concurrency thread-safety hashmap concurrenthashmap