Java HashMap 默认是不同步的。如果我们在多个线程正在添加和删除对的并发应用程序中从 HashMap 添加/删除键值对,我们最终可能会出现不一致的映射状态。学习同步 hashmap 和 ConcurrentHashMap 在 Java 中。
如果我们希望在并发环境中使用 Map,我们的首选应该始终是使用 ConcurrentHashMap
类。 ConcurrentHashMap
通过设计支持并发访问它的键值对。我们不需要执行任何额外的代码修改来启用地图同步。
请注意,从 ConcurrentHashMap
获得的 iterator 不会抛出 ConcurrentModificationException
。但是,迭代器被设计为一次只能由一个线程使用。这意味着我们从 ConcurrentHashMap 获得的每个迭代器都设计为由单个线程使用,不应传递。
如果我们这样做,则无法保证一个线程会看到另一个线程对映射所做的更改(无需从映射中获取新的迭代器)。 迭代器保证反映地图在创建时的状态。
让我们举一个使用 ConcurrentHashMap 的例子。
import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; public class HashMapExample { public static void main(String[] args) throws CloneNotSupportedException { ConcurrentHashMap<Integer, String> concurrHashMap = new ConcurrentHashMap<>(); //Put require no synchronization concurrHashMap.put(1, "A"); concurrHashMap.put(2, "B"); //Get require no synchronization concurrHashMap.get(1); Iterator<Integer> itr = concurrHashMap.keySet().iterator(); //Using synchronized block is advisable synchronized (concurrHashMap) { while(itr.hasNext()) { System.out.println(concurrHashMap.get(itr.next())); } } } }
程序输出。
A B
Synchronized HashMap 的工作方式也与 ConcurrentHashMap 非常相似,只有很少的区别。
SynchronizedHashMap
一次只允许一个线程执行读/写操作,因为它的所有方法都被声明为同步。 ConcurrentHashMap
允许多个线程在映射中的不同段上独立工作。这允许在 ConcurrentHashMap 中实现更高程度的并发,从而提高整个应用程序的性能。
来自这两个类的迭代器应该在 synchronized
块中使用,但是来自 SynchronizedHashMap 的迭代器是fail-fast。 ConcurrentHashMap 迭代器不是快速失败的。
import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class HashMapExample { public static void main(String[] args) throws CloneNotSupportedException { Map<Integer, String> syncHashMap = Collections.synchronizedMap(new HashMap<>()); //Put require no synchronization syncHashMap.put(1, "A"); syncHashMap.put(2, "B"); //Get require no synchronization syncHashMap.get(1); Iterator<Integer> itr = syncHashMap.keySet().iterator(); //Using synchronized block is advisable synchronized (syncHashMap) { while(itr.hasNext()) { System.out.println(syncHashMap.get(itr.next())); } } } }
程序输出。
A B
让我们找出两个版本的地图之间的一些差异,以便我们可以决定在哪种情况下选择哪个版本。
ConcurrentModificationException
如果一个线程试图修改它而另一个正在迭代它。迭代器反映了映射在创建时的状态。 SynchronizedHashMap 返回迭代器,它在并发修改时快速失败。快乐学习!!
阅读更多 :
Java HashMap 指南 HashMap Java 文档 ConcurrentHashMap Java 文档
地址:https://www.cundage.com/article/synchronize-hashmap.html