ConcurrentHashMap
在Java中有什么用途?它有哪些好处?它是如何工作的?提供示例代码会很有帮助。
ConcurrentHashMap
在Java中有什么用途?它有哪些好处?它是如何工作的?提供示例代码会很有帮助。
这段代码的意图是提供一个线程安全的HashMap
实现。多个线程可以同时读写它,而不会收到过时或损坏的数据。 ConcurrentHashMap
提供了自己的同步机制,因此您无需明确同步对其进行访问。
ConcurrentHashMap
的另一个特性是提供了putIfAbsent
方法,如果指定的键不存在,则会以原子方式添加映射。请考虑以下代码:
ConcurrentHashMap<String, Integer> myMap = new ConcurrentHashMap<String, Integer>();
// some stuff
if (!myMap.contains("key")) {
myMap.put("key", 3);
}
该代码不是线程安全的,因为在调用 contains
和调用 put
之间,另一个线程可能会为 "key"
添加映射。正确的实现应该是:
myMap.putIfAbsent("key", 3);
String
键; 如果 string1.equals(string2)&&string1!=string2
,我仍然可以在ConcurrentHashMap
中获取该项吗? - Andrew WyldConcurrentHashMap
允许并发访问映射。HashTable也提供了对映射的同步访问,但需要锁住整个映射以执行任何操作。
ConcurrentHashMap
的逻辑是,只有一部分[segments
]被锁定,而不是锁定整个表。每个段管理其自己的HashTable。仅对更新应用锁定。在检索的情况下,它允许完全并发性。
假设有四个线程同时在容量为32的映射上工作,该表被分成四个段,每个段管理一个具有容量的哈希表。默认情况下,该集合维护16个段的列表,每个段用于保护(或锁定)映射的单个桶。
这实际上意味着可以同时修改16个线程的集合。使用可选的concurrencyLevel构造函数参数可以增加并发级别。
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel)
就像其他回答所述,ConcurrentHashMap提供了新的方法putIfAbsent()
,该方法类似于put,但如果键已经存在,则不会覆盖该值。
private static Map<String,String> aMap =new ConcurrentHashMap<String,String>();
if(!aMap.contains("key"))
aMap.put("key","value");
新方法也更快,因为它避免了像上面的双重遍历
。 contains
方法必须定位段并迭代表格以查找键,再次,方法put
必须遍历桶并放置键。
真正的功能区别在于,在您使用时,如果其他人更改它,它不会抛出异常和/或损坏。
对于普通的集合,如果另一个线程在您访问(通过迭代器)时添加或删除元素,它将抛出异常。ConcurrentHashMap允许它们进行更改并且不停止您的线程。
请注意,它不提供任何同步保证或承诺线程之间变化的瞬时可见性。(它有点像读提交的数据库隔离级别,而不是行锁定的序列化数据库隔离级别。 (老派的行锁定SQL序列化,而不是Oracle风格的多版本序列化 :))
我知道的最常见的用途是在App Server环境中缓存不可变派生信息,许多线程可能正在访问相同的东西,并且如果两个线程交错计算相同的缓存值并将其放入两次,这并不重要等等。(例如,它在Spring WebMVC框架内广泛用于保存运行时派生配置,例如从URL到处理程序方法的映射。)
它可以用于记忆化:
import java.util.concurrent.ConcurrentHashMap;
public static Function<Integer, Integer> fib = (n) -> {
Map<Integer, Integer> cache = new ConcurrentHashMap<>();
if (n == 0 || n == 1) return n;
return cache.computeIfAbsent(n, (key) -> HelloWorld.fib.apply(n - 2) + HelloWorld.fib.apply(n - 1));
};
import java.util.concurrent.*;
class ConcurrentHashMapDemo {
public static void main(String[] args)
{
ConcurrentHashMap m = new ConcurrentHashMap();
m.put(1, "Hello");
m.put(2, "Vala");
m.put(3, "Sarakar");
// Here we cant add Hello because 1 key
// is already present in ConcurrentHashMap object
m.putIfAbsent(1, "Hello");
// We can remove entry because 2 key
// is associated with For value
m.remove(2, "Vala");
// Now we can add Vala
m.putIfAbsent(4, "Vala");
System.out.println(m);
}
}
1.ConcurrentHashMap是线程安全的,这意味着代码一次只能被单个线程访问。
2.ConcurrentHashMap在Map的特定部分上进行同步或锁定。为了优化ConcurrentHashMap的性能,Map根据并发级别划分成不同的分区。这样我们就不需要同步整个Map对象。
3.默认的并发级别是16,因此Map被划分为16个部分,每个部分由不同的锁控制,这意味着可以有16个线程操作。
4.ConcurrentHashMap不允许NULL值。因此,在ConcurrentHashMap中,键不能为null。