【问题标题】:How to implement concurrent clear and copy map for ConcurrentHashMapConcurrentHashMap如何实现并发清拷贝映射
【发布时间】:2018-05-04 08:28:25
【问题描述】:

在我的项目中,我构建了 Jersey Web 服务。该服务有计划任务,每分钟运行一次并填充(通过 putIfAbsent 函数)并发哈希映射(但之前清除它)。此外,Web 服务具有返回地图 json 的端点:

return gson.toJson(map, type)

通过 JAVA API 函数 clear 不是并发函数,gson.toJson 只使用 Map API 函数,所以我需要并发 clear 和 getMap/copyMap 函数。所以我想通过并发函数使用自己实现这些功能:

public class ExtendedConcurrentHashMap<K,V> extends ConcurrentHashMap<K,V> {
  private final ConcurrentHashMap<K,V> map;

  public ExtendedConcurrentHashMap(ConcurrentHashMap<K,V> map) {
    this.map = map;
  }

  public void clear() {
    ConcurrentHashMap.KeySetView<K,V> keySet = map.keySet(); //concurrent function
    Iterator<K> iterator = keySet.iterator();

    while(iterator.hasNext()) {
      K keyToRemove = iterator.next();
      map.compute(keyToRemove, (key,value) -> null); // concurrent function
    }
  }

  public Map<K,V> getMap() {
    Map<K,V> mapCopy = new HashMap<>();
    map.forEach((key,value) -> mapCopy.put(key,value)); // concurrent function

    return mapCopy;
  }
}

这是正确的方法吗?我不想使用读/写锁或同步函数,因为从端点性能获取 json 对于我的 Web 服务非常重要。

部分填充的地图不会打扰我。在读/写/更新期间获得性能而不是获得异常对我来说最重要

【问题讨论】:

  • clear() 如果你使用 concurenthashmap 是线程安全的
  • 只需使用Collections.synchronizedMap 包装一个普通的HashMap。这将为您提供一致的数据视图。
  • @teppic 并在多线程环境中杀死性能:)
  • @Cargeh:我保证 op 不会注意到差异。
  • 为什么不使用 volatile 字段交换为不可变映射?这样你就不会看到部分人口稠密的地图了

标签: java concurrency gson concurrenthashmap


【解决方案1】:

ConcurrentHashMap 中的Map.clear() 的实现线程安全的。文档中的 cmets 指的是从不同线程查看时数据的一致性:

对于 putAllclear 等聚合操作,并发检索可能仅反映插入或删除某些条目。

您的解决方案遇到了同样的问题,并且由于ConcurrentHashMap 中没有全局锁(实际上,读取从不锁),因此无法使该方法起作用。

如果您想以原子方式执行批量操作,则必须手动进行锁定。 Collections.synchronizedMap() 提供了一个使这变得简单的包装器。包装器本身用作所有操作的锁,因此在其上进行同步可以执行多个操作,而不必担心其他线程会在工作完成之前执行更新或读取。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 2015-08-23
    • 1970-01-01
    • 2013-03-19
    • 2012-02-19
    • 2016-03-20
    • 2015-06-12
    相关资源
    最近更新 更多