- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 ConcurrentHashMap<String,List<String>>
由线程访问,线程在附加值之前检查键是否存在。我通过使用 synchronized
得到了这个关键词。如果synchronized
未使用关键字则值是错误的。不是 ConcurrentHashMap
线程安全?还是这段代码有问题?是否可以在不使用 synchronized
的情况下使此代码正常工作以获得更好的性能?这是执行此操作的代码。
ExecutorService executorService = Executors.newFixedThreadPool(4);
final ConcurrentLinkedQueue<Future<?>> futures = new ConcurrentLinkedQueue<Future<?>>();
final ConcurrentHashMap<String, List<String>> map = new ConcurrentHashMap<String, List<String>>();
final JsonParser parser = new JsonParser();
File[] files = new File(dir).listFiles();
for (final File tfile : files) {
futures.add((Future<String>) executorService.submit(new Runnable() {
public void run() {
Object obj = parser.parse(new FileReader(tfile.getAbsolutePath()));
JsonObject jsonObject = (JsonObject) obj;
String documentname = obj.get("name").toString();
synchronized (map) {
List<String> paths = new ArrayList<String>();
//if key already exists append new path to the value
if (map.containsKey(documentname)) {
paths = map.get(documentname);
}
paths.add(tfile.getAbsolutePath());
map.put(documentname, paths);
}
}
}));
}
最佳答案
你可以尝试替换这个:
String documentname = obj.get("name").toString();
List<String> paths = new ArrayList<String>();
//if key already exists append new path to the value
if (map.containsKey(documentname)) {
paths = map.get(documentname);
}
paths.add(tfile.getAbsolutePath());
map.put(documentname, paths);
用这个:
String documentname = obj.get("name").toString();
List<String> paths = Collections.synchronizedList(new ArrayList<String>());
List<String> existing = map.putIfAbsent(documentname, paths);
if (existing != null) {
paths = existing;
}
paths.add(tfile.getAbsolutePath());
putIfAbsent方法避免了如果两个线程都尝试检查(使用 containsKey)然后将条目放入映射时发生的竞争条件。
synchronizedList方法用同步包装器包装嵌套集合,这样您就不需要同步对嵌套集合的访问。或者,您可以使用 java.util.concurrent 中的并发数据结构。
ThreadSafe是一个发现并发错误的静态分析工具。它可以独立运行,可以在 Eclipse 中运行,也可以用作 SonarQube 插件。特别是,它有一个针对您显示的代码中的两个错误的检查器:
我建议的使用 putIfAbsent 的代码的一个问题是它总是创建一个集合。当映射已经包含给定键的条目时,新集合将被简单地丢弃。但是,这可能对您的应用程序来说效率低下,并且会给垃圾收集器带来额外的压力。
因此,您可能需要考虑这样的事情:
String documentname = obj.get("name").toString();
List<String> paths = map.get(documentname);
if (paths == null) {
paths = Collections.synchronizedList(new ArrayList<String>());
List<String> existing = map.putIfAbsent(documentname, paths);
if (existing != null) {
paths = existing;
}
paths.add(tfile.getAbsolutePath());
}
请注意此 ThreadSafe non-atomic get-check-put 中屏幕左下角的“规则描述”链接。关联。单击“规则描述”链接以进一步解释 get-check-put 问题及其可能的解决方案。
关于java - 没有 synchronized 关键字的 ConcurrentHashMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33399075/
我最初构造了一系列嵌套的 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
我是一名优秀的程序员,十分优秀!