Java中的ConcurrentHashMap

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 ConcurrentModificationException.

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

并发哈希图 (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 HashMap, except that it’s thread-safe and allows modification while iteration.

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

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<String,String> myMap = new ConcurrentHashMap<String,String>();
		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<String> 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<String,String>();
		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<String> 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 Java Generics Example.

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

You should also read Java Collections Interview Questions and Iterator Design Pattern in Java.

您还应该阅读Java中的Java Collections面试问题迭代器设计模式

GitHub Repository. GitHub Repository中检出更多Java集合示例。

Reference: API Doc

参考: API文档

翻译自: https://www.journaldev.com/122/concurrenthashmap-in-java

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值