博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java中的ConcurrentHashMap
阅读量:2528 次
发布时间:2019-05-11

本文共 5888 字,大约阅读时间需要 19 分钟。

Java ConcurrentHashMap class is part of the Concurrency Collection Classes. It’s a hash table implementation, which supports concurrent retrieval and updates. It’s used in a multi-threaded environment to avoid .

Java ConcurrentHashMap类是并发集合类的一部分。 这是一个哈希表实现,支持并发检索和更新。 在多线程环境中使用它可以避免 。

并发哈希图 (ConcurrentHashMap)

If we try to modify the collection while iterating over it, we get ConcurrentModificationException. Java 1.5 introduced Concurrent classes in the java.util.concurrent package to overcome this scenario. ConcurrentHashMap is the Map implementation that allows us to modify the Map while iteration. The ConcurrentHashMap operations are thread-safe. ConcurrentHashMap doesn’t allow null for keys and values.

如果我们尝试在迭代集合时修改集合,则会得到ConcurrentModificationException 。 Java 1.5在java.util.concurrent包中引入了Concurrent类来克服这种情况。 ConcurrentHashMap是Map实现,它允许我们在迭代时修改Map。 ConcurrentHashMap操作是线程安全的。 ConcurrentHashMap不允许键和值为null。

Java ConcurrentHashMap示例 (Java ConcurrentHashMap Example)

The ConcurrentHashMap class is similar to , except that it’s thread-safe and allows modification while iteration.

ConcurrentHashMap类与相似,但它是线程安全的,并允许在迭代时进行修改。

package com.journaldev.util;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;public class ConcurrentHashMapExample {	public static void main(String[] args) {		//ConcurrentHashMap		Map
myMap = new ConcurrentHashMap
(); myMap.put("1", "1"); myMap.put("2", "1"); myMap.put("3", "1"); myMap.put("4", "1"); myMap.put("5", "1"); myMap.put("6", "1"); System.out.println("ConcurrentHashMap before iterator: "+myMap); Iterator
it = myMap.keySet().iterator(); while(it.hasNext()){ String key = it.next(); if(key.equals("3")) myMap.put(key+"new", "new3"); } System.out.println("ConcurrentHashMap after iterator: "+myMap); //HashMap myMap = new HashMap
(); myMap.put("1", "1"); myMap.put("2", "1"); myMap.put("3", "1"); myMap.put("4", "1"); myMap.put("5", "1"); myMap.put("6", "1"); System.out.println("HashMap before iterator: "+myMap); Iterator
it1 = myMap.keySet().iterator(); while(it1.hasNext()){ String key = it1.next(); if(key.equals("3")) myMap.put(key+"new", "new3"); } System.out.println("HashMap after iterator: "+myMap); }}

Output:

输出

ConcurrentHashMap before iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1}ConcurrentHashMap after iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 4=1, 2=1}HashMap before iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1}Exception in thread "main" java.util.ConcurrentModificationException	at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)	at java.util.HashMap$KeyIterator.next(HashMap.java:828)	at com.test.ConcurrentHashMapExample.main(ConcurrentHashMapExample.java:44)

It’s clear from the output that ConcurrentHashMap takes care of the new entry in the map while iteration whereas HashMap throws ConcurrentModificationException.

从输出中可以清楚地看到, ConcurrentHashMap在迭代时会处理映射中的新条目,而HashMap则抛出ConcurrentModificationException

Let’s look at the exception stack trace closely. The following statement has thrown Exception.

让我们仔细看看异常堆栈跟踪。 以下语句引发了Exception。

String key = it1.next();

It means that the new entry got inserted in the HashMap but Iterator is failing. Actually, Iterator on Collection objects is fail-fast i.e any modification in the structure or the number of entries in the collection object will trigger the exception.

这意味着新条目已插入HashMap中,但Iterator失败。 实际上,对Collection对象的Iterator是快速失败的,即,对结构的任何修改或collection对象中条目的数量都会触发异常。

迭代器如何知道Collection中的修改? (How does iterator know about the modification in the Collection?)

We have taken the set of keys from HashMap and then iterating over it.

我们从HashMap中获取了一组键,然后对其进行迭代。

HashMap contains a variable to count the number of modifications and iterator use it when you call its next() function to get the next entry.

HashMap包含一个变量,用于计算修改次数,并且迭代器在调用其next()函数以获取下一个条目时使用它。

HashMap.java:

HashMap.java

/**     * The number of times this HashMap has been structurally modified     * Structural modifications are those that change the number of mappings in     * the HashMap or otherwise modify its internal structure (e.g.,     * rehash).  This field is used to make iterators on Collection-views of     * the HashMap fail-fast.  (See ConcurrentModificationException).     */    transient volatile int modCount;

Let’s change the code a little bit to come out of the iterator loop when we insert the new entry. All we need to do is add a break statement after the put call.

当我们插入新条目时,让我们稍微更改一下代码使其从迭代器循环中出来。 我们需要做的就是在put调用之后添加一个break语句。

if(key.equals("3")){	myMap.put(key+"new", "new3");	break;}

The output with the above code:

上面的代码输出:

ConcurrentHashMap before iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1}ConcurrentHashMap after iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 4=1, 2=1}HashMap before iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1}HashMap after iterator: {3=1, 2=1, 1=1, 3new=new3, 6=1, 5=1, 4=1}

如果修改键值会怎样? (What happens if the key value is modified?)

What if we don’t add a new entry but update the existing key-value pair?

如果我们不添加新条目而是更新现有的键值对怎么办?

Will it throw exception?

会抛出异常吗?

Let’s change the code in the original program and check it out.

让我们在原始程序中更改代码并签出。

//myMap.put(key+"new", "new3");myMap.put(key, "new3");

There won’t be any exception because the collection is modified but its structure remains the same.

不会有任何例外,因为集合已被修改,但其结构保持不变。

进一步阅读 (Further Reading)

Did you notice those angle brackets while creating our collection object and Iterator?

在创建我们的集合对象和迭代器时,您是否注意到那些尖括号?

It’s called generics and it’s very powerful when it comes to type-checking at compile time to remove ClassCastException at runtime. Learn more about generics in .

它被称为泛型,当在编译时进行类型检查以在运行时删除ClassCastException时,它非常强大。 在了解有关泛型的更多信息。

You should also read and .

您还应该阅读和 。

. 检出更多Java集合示例。

Reference:

参考:

翻译自:

转载地址:http://aaozd.baihongyu.com/

你可能感兴趣的文章
ThreadLocal为什么要用WeakReference
查看>>
删除本地文件
查看>>
FOC实现概述
查看>>
base64编码的图片字节流存入html页面中的显示
查看>>
这个大学时代的博客不在维护了,请移步到我的新博客
查看>>
GUI学习之二十一——QSlider、QScroll、QDial学习总结
查看>>
nginx反向代理docker registry报”blob upload unknown"解决办法
查看>>
gethostbyname与sockaddr_in的完美组合
查看>>
kibana的query string syntax 笔记
查看>>
旋转变换(一)旋转矩阵
查看>>
thinkphp3.2.3 bug集锦
查看>>
[BZOJ 4010] 菜肴制作
查看>>
C# 创建 读取 更新 XML文件
查看>>
KD树
查看>>
VsVim - Shortcut Key (快捷键)
查看>>
C++练习 | 模板与泛式编程练习(1)
查看>>
HDU5447 Good Numbers
查看>>
08.CXF发布WebService(Java项目)
查看>>
java-集合框架
查看>>
RTMP
查看>>