- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个 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/
我最初构造了一系列嵌套的 ConcurrentHashMaps private final ConcurrentHashMap allInOne = new ConcurrentHashMap
我正在尝试使用 ConcurrentHashMap 初始化 ConcurrentHashMap private final ConcurrentHashMap > myMulitiConcurrent
为了提高工作效率,我尝试将数据保存在一个动态容器中。 我在 class 中初始化它与 private final ConcurrentHashMap allInOne = new Concur
我正在创建基于 Socket 的服务器-客户端预订服务,并且遇到有关将由多个线程访问的类的问题,是否需要扩展 ConcurrentHashMap 或创建变量 ConcurrentHashMap 是否足
从 Javadoc 我知道 ConcurrentHashMap.replace 是原子的,但是 ConcurrentHashMap.put 呢?我看到它们在源代码中的实现方式不同,但我无法弄清楚它们的
是 ConcurrentHashMap.get() 保证看到以前的ConcurrentHashMap.put()通过不同的线程?我的期望是,阅读 JavaDocs 似乎表明了这一点,但我 99% 确信
使用 ConcurrentHashMap,我发现 computeIfAbsent 比 putIfAbsent 慢两倍。这里是简单的测试: import java.util.ArrayList; imp
我有一个以下格式的 ConcurrentHashMap: ConcurrentHashMap> 现在在此 map 中,我想删除数组列表中的特定值。任何人都可以指导这一点。 编辑1:我有一张 map >
为什么 ConcurrentHashMap.Segment 和 ConcurrentHashMap.HashEntry 类是静态的?为什么要这样设计? 最佳答案 基本上所有不需要使用其封闭类属性的内部
在 ConcurrentHashMap 中通过键递增并发计数器时,使用常规 Int 作为值是否安全,还是我们必须使用 AtomicInteger?例如考虑以下两个实现 ConcurrentHashMa
我对java中的并发数据结构有疑问,特别是: 1) ConcurrentHashMap 2) HashMap 3) ConcurrentHashMap 如果我理解正确的话: 1) 读/写是线程安全的,
我正在尝试查看实际的 Java 文档,描述传递给 ConcurrentHashMap.computeIfAbsent 和 ConcurrentHashMap.computeIfPresent< 时可以
我有一个名为 SerializableL 的接口(interface)由 3 个不同的类实现: 产品 横幅 标签 我开始重构,想用多个方法调用替换多个段落。 public void load(Conc
一 JDK 中的 ConcurrentHashMap 在 JDK 8以前,HashMap 是基于数组 + 链表来实现的。整体上看,HashMap 是一个数组,但每个数组元素又是一张链表。 当向 Has
我想知道当我们在调整大小时尝试读取 ConcurrentHashMap 时可能发生的情况。 我知道在读取期间,第一次尝试总是不同步的。在第二次尝试中,它将尝试获取锁并重试。 但是,如果它在调整大小时发
在一个应用程序中,1 个线程负责不断更新映射,主线程定期读取映射,使用 ConcurrentHashmap 是否足够?或者我应该明确地锁定同步块(synchronized block)中的操作吗?任何
介绍 ConcurrentHashMap 技术是为了解决问题而生的,ConcurrentHashMap 解决了多个线程同时操作一个 HashMap 时,可能出现的内部问题。当多个线程同时操作一
我有一个由多个线程访问的键值映射: private final ConcurrentMap key_vval_map = new ConcurrentHashMap(); 我的自定义 get() 和
谁能告诉我这段代码出了什么问题?我要拔头发了! 如果我使用 HashMap 而不是 ConcurrentHashMap 则没有任何问题。代码使用JDK 5.0编译 public class MapTe
来自 ConcurrentHashMap 的源码 /** 171 * Number of unsynchronized retries in size and containsVal
我是一名优秀的程序员,十分优秀!