Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 什么';ConcurrentHashMap和Collections.synchronizedMap(映射)之间的区别是什么?_Java_Dictionary_Concurrency - Fatal编程技术网

Java 什么';ConcurrentHashMap和Collections.synchronizedMap(映射)之间的区别是什么?

Java 什么';ConcurrentHashMap和Collections.synchronizedMap(映射)之间的区别是什么?,java,dictionary,concurrency,Java,Dictionary,Concurrency,我有一个映射,它将由多个线程同时修改 Java API中似乎有三种不同的同步映射实现: Hashtable Collections.synchronizedMap(地图) ConcurrentHashMap 据我所知,Hashtable是一个旧的实现(扩展了过时的Dictionary类),后来进行了修改以适应Map接口。虽然它是同步的,但似乎有严重的问题,不鼓励新项目 但是另外两个呢?Collections.synchronizedMap(Map)和ConcurrentHashMaps返回的

我有一个映射,它将由多个线程同时修改

Java API中似乎有三种不同的同步映射实现:

  • Hashtable
  • Collections.synchronizedMap(地图)
  • ConcurrentHashMap
据我所知,
Hashtable
是一个旧的实现(扩展了过时的
Dictionary
类),后来进行了修改以适应
Map
接口。虽然它是同步的,但似乎有严重的问题,不鼓励新项目


但是另外两个呢?
Collections.synchronizedMap(Map)
ConcurrentHashMap
s返回的映射之间有什么区别?哪一个适合哪种情况?

根据您的需要,使用
ConcurrentHashMap
。它允许从多个线程并发修改映射,而无需阻止它们<代码>集合。synchronizedMap(map)会创建一个阻塞映射,这会降低性能,但会确保一致性(如果使用正确)


如果需要确保数据一致性,并且每个线程都需要有地图的最新视图,请使用第二个选项。如果性能非常关键,并且每个线程只向映射插入数据,读取的频率较低,则使用第一个线程。

如果可以使用ConcurrentHashMap,则首选ConcurrentHashMap,尽管它至少需要Java 5

它被设计成在多线程使用时可以很好地伸缩。当一次只有一个线程访问Map时,性能可能会稍差,但当多个线程同时访问Map时,性能会显著提高

我找到了一张复制了这本好书的桌子的桌子,我完全推荐这本书


Collections.synchronizedMap只有在您需要使用其他一些特征(可能是某种有序映射,如树形映射)来包装映射时才有意义。

  • 并且不允许使用
    null
    键或
    null

  • 同步所有操作(
    get
    put
    size
    等)

  • 支持检索的完全并发性和更新的可调整预期并发性


和往常一样,还涉及到并发性(开销)和速度权衡。您确实需要考虑应用程序的详细并发需求来作出决定,然后测试代码是否足够好。< /P>

CONCURNESHASMAP是为并发访问优化的。


访问不会锁定整个映射,而是使用更细粒度的策略,这提高了可伸缩性。还有一些专门针对并发访问的功能增强,例如并发迭代器。

您对哈希表的看法是正确的,您可以忽略它

提到虽然HashTable和synchronized wrapper类通过一次只允许一个线程访问映射来提供基本的线程安全性,但这不是“真正的”线程安全性,因为许多复合操作仍然需要额外的同步,例如:

synchronized (records) {
  Record rec = records.get(id);
  if (rec == null) {
      rec = new Record(id);
      records.put(id, rec);
  }
  return rec;
}
但是,不要认为
ConcurrentHashMap
是具有如上所示的典型
synchronized
块的
HashMap
的简单替代方案。阅读文章以更好地理解其复杂性。

哈希表的“可伸缩性问题”在
集合中以完全相同的方式出现。synchronizedMap(Map)
-它们使用非常简单的同步,这意味着只有一个线程可以同时访问映射

当您进行简单的插入和查找时,这不是什么大问题(除非您进行了非常密集的插入和查找),但当您需要迭代整个映射时,这会成为一个大问题,对于一个大型映射,这可能需要很长的时间-当一个线程执行此操作时,所有其他线程都必须等待,如果他们想要插入或查找任何内容


ConcurrentHashMap
使用非常复杂的技术来减少同步需求,允许多线程在不同步的情况下进行并行读取访问,更重要的是,它提供了一个不需要同步的
迭代器,甚至允许在交互过程中修改映射(虽然它不能保证在迭代过程中插入的元素是否会被返回)。

一般来说,如果您想使用
ConcurrentHashMap
请确保您准备好错过“更新”
(即,打印HashMap的内容并不保证它会打印最新的映射)并使用类似于
CyclicBarrier
的API来确保整个程序生命周期的一致性。

以下是一些:

1) ConcurrentHashMap只锁定映射的一部分,而SynchronizedMap锁定整个映射。
2) ConcurrentHashMap比SynchronizedMap具有更好的性能和更大的可扩展性。
3) 在多个读卡器和单个写卡器的情况下,ConcurrentHashMap是最佳选择


此文本来自
ConcurrentHashMap
中的,锁应用于段而不是整个映射。 每个段管理自己的内部哈希表。锁定仅应用于更新操作<代码>集合。同步地图(地图)
同步整个地图

  • 如果数据一致性非常重要-请使用哈希表或Collections.synchronizedMap(映射)
  • 如果速度/性能非常重要,并且数据更新可能受到影响,请使用ConcurrentHashMap
  • ╔═══════════════╦═══════════════════╦═══════════════════╦═════════════════════╗
    ║   财产║     哈希映射║    哈希表║  ConcurrentHashMap║
    ╠═══════════════╬═══
    
       public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
            return new SynchronizedMap<>(m);
        }
    
     private static class SynchronizedMap<K,V>
            implements Map<K,V>, Serializable {
            private static final long serialVersionUID = 1978198479659022715L;
    
            private final Map<K,V> m;     // Backing Map
            final Object      mutex;        // Object on which to synchronize
    
            SynchronizedMap(Map<K,V> m) {
                this.m = Objects.requireNonNull(m);
                mutex = this;
            }
    
            SynchronizedMap(Map<K,V> m, Object mutex) {
                this.m = m;
                this.mutex = mutex;
            }
    
            public int size() {
                synchronized (mutex) {return m.size();}
            }
            public boolean isEmpty() {
                synchronized (mutex) {return m.isEmpty();}
            }
            public boolean containsKey(Object key) {
                synchronized (mutex) {return m.containsKey(key);}
            }
            public boolean containsValue(Object value) {
                synchronized (mutex) {return m.containsValue(value);}
            }
            public V get(Object key) {
                synchronized (mutex) {return m.get(key);}
            }
    
            public V put(K key, V value) {
                synchronized (mutex) {return m.put(key, value);}
            }
            public V remove(Object key) {
                synchronized (mutex) {return m.remove(key);}
            }
            public void putAll(Map<? extends K, ? extends V> map) {
                synchronized (mutex) {m.putAll(map);}
            }
            public void clear() {
                synchronized (mutex) {m.clear();}
            }
    
            private transient Set<K> keySet;
            private transient Set<Map.Entry<K,V>> entrySet;
            private transient Collection<V> values;
    
            public Set<K> keySet() {
                synchronized (mutex) {
                    if (keySet==null)
                        keySet = new SynchronizedSet<>(m.keySet(), mutex);
                    return keySet;
                }
            }
    
            public Set<Map.Entry<K,V>> entrySet() {
                synchronized (mutex) {
                    if (entrySet==null)
                        entrySet = new SynchronizedSet<>(m.entrySet(), mutex);
                    return entrySet;
                }
            }
    
            public Collection<V> values() {
                synchronized (mutex) {
                    if (values==null)
                        values = new SynchronizedCollection<>(m.values(), mutex);
                    return values;
                }
            }
    
            public boolean equals(Object o) {
                if (this == o)
                    return true;
                synchronized (mutex) {return m.equals(o);}
            }
            public int hashCode() {
                synchronized (mutex) {return m.hashCode();}
            }
            public String toString() {
                synchronized (mutex) {return m.toString();}
            }
    
            // Override default methods in Map
            @Override
            public V getOrDefault(Object k, V defaultValue) {
                synchronized (mutex) {return m.getOrDefault(k, defaultValue);}
            }
            @Override
            public void forEach(BiConsumer<? super K, ? super V> action) {
                synchronized (mutex) {m.forEach(action);}
            }
            @Override
            public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
                synchronized (mutex) {m.replaceAll(function);}
            }
            @Override
            public V putIfAbsent(K key, V value) {
                synchronized (mutex) {return m.putIfAbsent(key, value);}
            }
            @Override
            public boolean remove(Object key, Object value) {
                synchronized (mutex) {return m.remove(key, value);}
            }
            @Override
            public boolean replace(K key, V oldValue, V newValue) {
                synchronized (mutex) {return m.replace(key, oldValue, newValue);}
            }
            @Override
            public V replace(K key, V value) {
                synchronized (mutex) {return m.replace(key, value);}
            }
            @Override
            public V computeIfAbsent(K key,
                    Function<? super K, ? extends V> mappingFunction) {
                synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
            }
            @Override
            public V computeIfPresent(K key,
                    BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
                synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
            }
            @Override
            public V compute(K key,
                    BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
                synchronized (mutex) {return m.compute(key, remappingFunction);}
            }
            @Override
            public V merge(K key, V value,
                    BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
                synchronized (mutex) {return m.merge(key, value, remappingFunction);}
            }
    
            private void writeObject(ObjectOutputStream s) throws IOException {
                synchronized (mutex) {s.defaultWriteObject();}
            }
        }