Java 不带集合的线程安全LinkedHashMap.synchronized

Java 不带集合的线程安全LinkedHashMap.synchronized,java,multithreading,data-structures,concurrency,oracle-maf,Java,Multithreading,Data Structures,Concurrency,Oracle Maf,我使用的是LinkedHashMap,环境是多线程的,所以这个结构需要是线程安全的。在特定的事件中,我需要读取整个地图并将其推送到db并清除所有 大多数情况下,仅写入此映射。此地图最多有50个条目 我使用的是Oracle MAF,它没有Collections.syncronizedMap可用。那么,我需要在同步块中放入哪些内容来确保写入和读取不会影响我的concurrentModificationException等 几项要求: 我需要将其表现为循环队列,以便覆盖LinkedHashMap的Re

我使用的是LinkedHashMap,环境是多线程的,所以这个结构需要是线程安全的。在特定的事件中,我需要读取整个地图并将其推送到db并清除所有

大多数情况下,仅写入此映射。此地图最多有50个条目

我使用的是Oracle MAF,它没有Collections.syncronizedMap可用。那么,我需要在同步块中放入哪些内容来确保写入和读取不会影响我的concurrentModificationException等

几项要求:

  • 我需要将其表现为循环队列,以便覆盖LinkedHashMap的RemoveedStantry方法
  • 我需要维持秩序

  • 如果您使用的是java 1.5版或更高版本,则可以使用

    这是在多线程环境中使用的映射的最有效实现

    它还添加了一些方法,如
    putIfAbsent
    对地图上的原子操作非常有用

    从java文档:

    检索操作(包括get)通常不会阻止,因此可能 与更新操作重叠(包括放置和删除)。检索 反映最近完成的更新操作的结果 坚持他们的开始用于聚合操作如putAll和 清除并发检索可能只反映插入或删除 一些条目

    因此,请确认这是您期望从您的类中获得的行为


    如果您的地图只有50条记录,并且需要用作循环队列,为什么要使用地图?使用其中一个队列实现不是更好吗


    如果需要使用LinkedHashMap,请使用以下选项:

    Map m = Collections.synchronizedMap(new LinkedHashMap());
    
    从LinkedHashMap的

    请注意,此实现是不同步的。如果有多个线程 同时访问链接的哈希映射,并至少访问其中一个线程 如果从结构上修改贴图,则必须从外部对其进行同步。 这通常是通过在某个 自然地封装了地图。如果不存在这样的对象,则映射 应使用Collections.synchronizedMap方法“包装”。这 最好在创建时执行,以防止意外的不同步 访问地图:

     Map m = Collections.synchronizedMap(new LinkedHashMap(...));
    

    那么,我需要在同步块中放入哪些内容来确保写入和读取不会影响我的concurrentModificationException等

    方法调用的所有内容都应在同步块中

    棘手的一点是迭代器的使用,因为您必须在迭代器的生命周期中保持锁。e、 g

    // pre Java 5.0 code
    synchronized(map) { // the lock has to be held for the whole loop.
        for(Iterator iter = map.entrySet().iterator(); iter.hashNext(); ) {
             Map.Entry entry = iter.next();
             String key = (String) entry.getKey();
             MyType value = (MyType) entry.getValue();
             // do something with key and value.
        }
    }
    

    在多线程环境中,大多数
    LinkedHashMap
    操作都需要
    同步
    ,即使是那些看起来纯粹像
    get(key)
    get(key)
    的操作实际上也会变异一些内部节点。最简单的方法是使用
    Collections.synchronizedMap

    Map<K,V> map = Collections.synchronizedMap(new LinkedHashMap<>());
    

    每次在hasmap上调用一个方法时,比如
    get
    put
    ,都需要用同步来围绕它。如果一行中有多个呼叫,可以用一次同步将它们全部包围起来。发布一些代码。在写入db时不要同步映射。制作一个副本(在synchronized{})中,将副本写入db。您看到了什么好处?我的地图最多可以容纳50个条目。我相信创建副本所需的时间与在副本上进行迭代所需的时间相同。因此,我的迭代方式类似于(diagMap!=null&&diagMap.size()>0){Set keys=diagMap.keySet();for(Date key:keys){String value=diagMap.get(key);dPath.append(key).append(DELIM).append(value);}}}它不会在for循环之后释放迭代器吗?我相信它不支持重写RemoveEdestEntry方法以使其行为像我在帖子中所说的循环队列一样,我的env中没有Collections.synchronizedMap,它使用受限的jdk配置文件,因此我认为您只能使用synchronized或使用自定义数据结构来包围代码。我需要为所有LinkedHashMap操作都这样做吗?好的,我认为最好在Get和puts周围使用synchronized块
    class SyncMap<T,U> implements Map<T,U>{
      SyncMap<T,U>(LinkedHashMap<T,U> map){
       ..
      }
      public synchronized U get(T t){
        ..
      }
    }