Java中的ConcurrentHashMap?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2836267/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ConcurrentHashMap in Java?
提问by Praveen
What is the use of ConcurrentHashMap
in Java? What are its benefits? How does it work?
Sample code would be useful too.
ConcurrentHashMap
在Java中有什么用?它有什么好处?它是如何工作的?示例代码也很有用。
采纳答案by danben
The point is to provide an implementation of HashMap
that is threadsafe. Multiple threads can read from and write to it without the chance of receiving out-of-date or corrupted data. ConcurrentHashMap
provides its own synchronization, so you do not have to synchronize accesses to it explicitly.
关键是提供一个HashMap
线程安全的实现。多个线程可以读取和写入它,而不会收到过时或损坏的数据。 ConcurrentHashMap
提供自己的同步,因此您不必显式同步对它的访问。
Another feature of ConcurrentHashMap
is that it provides the putIfAbsent
method, which will atomicallyadd a mapping if the specified key does not exist. Consider the following code:
的另一个特点ConcurrentHashMap
是它提供了putIfAbsent
方法,如果指定的键不存在,它将自动添加一个映射。考虑以下代码:
ConcurrentHashMap<String, Integer> myMap = new ConcurrentHashMap<String, Integer>();
// some stuff
if (!myMap.contains("key")) {
myMap.put("key", 3);
}
This code is not threadsafe, because another thread could add a mapping for "key"
between the call to contains
and the call to put
. The correct implementation would be:
这段代码不是线程安全的,因为另一个线程可以"key"
在对 的调用contains
和对 的调用之间添加映射put
。正确的实现是:
myMap.putIfAbsent("key", 3);
回答by Affe
Really the big functional difference is it doesn't throw an exception and/or end up corrupt when someone else changes it while you're using it.
实际上,最大的功能差异是它不会引发异常和/或在您使用它时其他人更改它时最终损坏。
With regular collections, if another thread adds or removes an element while you're access it (via the iterator) it will throw an exception. ConcurrentHashMap lets them make the change and doesn't stop your thread.
对于常规集合,如果另一个线程在您访问它时(通过迭代器)添加或删除元素,它将抛出异常。ConcurrentHashMap 允许他们进行更改并且不会停止您的线程。
Mind you it does not make any kind of synchronization guarantees or promises about the point-in-time visibility of the change from one thread to the other. (It's sort of like a read-committed database isolation, rather than a synchronized map which behaves more like a serializable database isolation. (old school row-locking SQL serializable, not Oracle-ish multiversion serializable :) )
请注意,它不会对从一个线程到另一个线程的更改的时间点可见性做出任何类型的同步保证或承诺。(它有点像一个读提交的数据库隔离,而不是一个同步映射,它的行为更像是一个可序列化的数据库隔离。(老派行锁定 SQL 可序列化,而不是 Oracle 式的多版本可序列化 :))
The most common use I know of is in caching immutable derived information in App Server environments where many threads may be accessing the same thing, and it doesn't really matter if two happen to calculate the same cache value and put it twice because they interleave, etc. (e.g., it's used extensively inside the Spring WebMVC framework for holding runtime-derived config like mappings from URLs to Handler Methods.)
我所知道的最常见的用途是在 App Server 环境中缓存不可变的派生信息,其中许多线程可能正在访问同一事物,如果两个线程碰巧计算相同的缓存值并将其放入两次,因为它们交错,这并不重要等(例如,它在 Spring WebMVC 框架中广泛用于保存运行时派生的配置,例如从 URL 到处理程序方法的映射。)
回答by Thalaivar
ConcurrentHashMap
allow concurrent access to the map. HashTables too offers synchronized access to map, but your entire map is locked to perform any operation.
ConcurrentHashMap
允许并发访问地图。HashTables 也提供对地图的同步访问,但您的整个地图被锁定以执行任何操作。
The logic behind ConcurrentHashMap is that your entire table is not getting locked
, but only the portion[segments
]. Each segments manages its own HashTable. Locking is applied only for updates. In case of of retrievals, it allows full concurrency.
ConcurrentHashMap 背后的逻辑是your entire table is not getting locked
,但只有部分[ segments
]。每个段管理自己的哈希表。锁定仅适用于更新。在检索的情况下,它允许完全并发。
Let's take four threads are concurrently working on a map whose capacity is 32, the table is partitioned into four segments where each segments manages a hash table of capacity. The collection maintains a list of 16 segments by default, each of which is used to guard (or lock on) a single bucket of the map.
假设四个线程并发工作在一个容量为 32 的映射上,该表被划分为四个段,每个段管理一个容量的哈希表。该集合默认维护一个包含 16 个段的列表,每个段用于保护(或锁定)地图的单个存储桶。
This effectively means that 16 threads can modify the collection at a single time. This level of concurrency can be increased using the optional concurrencyLevel constructorargument.
这实际上意味着 16 个线程可以一次修改集合。可以使用可选的concurrencyLevel 构造函数参数提高这种并发级别。
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel)
As the other answer stated, the ConcurrentHashMap offers new method putIfAbsent()
which is similar to put except the value will not be overridden if the key exists.
正如另一个答案所述, ConcurrentHashMap 提供了putIfAbsent()
类似于 put 的新方法,但如果键存在,则不会覆盖该值。
private static Map<String,String> aMap =new ConcurrentHashMap<String,String>();
if(!aMap.contains("key"))
aMap.put("key","value");
The new method is also faster as it avoids double traversing
as above. contains
method has to locate the segment and iterate the table to find the key and again the method put
has to traverse the bucket and put the key.
新方法也更快,因为它避免double traversing
了上述情况。contains
方法必须定位段并迭代表以找到键,该方法put
必须再次遍历存储桶并放置键。
回答by weakish
It can be used for memoization:
它可用于记忆:
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));
};
回答by VAYU
1.ConcurrentHashMap is thread-safe that is the code can be accessed by single thread at a time .
1.ConcurrentHashMap 是线程安全的,即代码可以被单线程访问。
2.ConcurrentHashMap synchronizes or locks on the certain portion of the Map . To optimize the performance of ConcurrentHashMap , Map is divided into different partitions depending upon the Concurrency level . So that we do not need to synchronize the whole Map Object.
2.ConcurrentHashMap 同步或锁定 Map 的某个部分。为了优化 ConcurrentHashMap 的性能,根据并发级别将 Map 划分为不同的分区。这样我们就不需要同步整个 Map Object。
3.Default concurrency level is 16, accordingly map is divided into 16 part and each part is governed with a different lock that means 16 thread can operate.
3.默认并发级别为16,因此map被分为16个部分,每个部分用不同的锁管理,这意味着16个线程可以操作。
4.ConcurrentHashMap does not allow NULL values . So the key can not be null in ConcurrentHashMap .
4.ConcurrentHashMap 不允许 NULL 值。所以 ConcurrentHashMap 中的键不能为空。
回答by JegsVala
Hello guys today we discussed the ConcurrentHashMap.
What is ConcurrentHashMap?
大家好,今天我们讨论了 ConcurrentHashMap。
什么是 ConcurrentHashMap?
ConcurrentHashMap is a class it introduce in java 1.5 which implements the ConcurrentMap as well as the Serializable interface. ConcurrentHashMap is enhance the HashMap when it dealing with multiple Theading. As we know when the application has multiple threading HashMap is not a good choice because performance issue occurred.
ConcurrentHashMap 是它在 java 1.5 中引入的一个类,它实现了 ConcurrentMap 以及 Serializable 接口。ConcurrentHashMap 是在处理多个 Theading 时对 HashMap 的增强。我们知道当应用程序有多个线程时 HashMap 不是一个好的选择,因为会出现性能问题。
There are the some key point of ConcurrentHashMap.
ConcurrentHashMap 有一些关键点。
- Underling data structure for ConcurrentHashMap is HashTable.
- ConcurrentHashMap is a class, That class is thread safe, it means multiple thread can access on a single thread object without any complication.
- ConcurretnHashMap object is divided into number of segment according to the concurrency level.
- The Default Concurrency-level of ConcurrentHashMap is 16.
- In ConcurrentHashMap any number of Thread can perform the retrieval operation,But for updation in object Thread must lock the particular Segment in which thread want to operate.
- This type of locking mechanism is known as Segment-Locking OR Bucket-Locking.
- In ConcurrentHashMap the 16 updation operation perform at a time.
- Null insertion is not possible in ConcurrentHashMap.
- ConcurrentHashMap 的底层数据结构是 HashTable。
- ConcurrentHashMap 是一个类,该类是线程安全的,这意味着多个线程可以访问单个线程对象而没有任何复杂性。
- ConcurretnHashMap 对象根据并发级别分为多个段。
- ConcurrentHashMap 的默认并发级别为 16。
- ConcurrentHashMap中任意数量的Thread都可以进行检索操作,但是对于对象中的更新,Thread必须锁定线程想要操作的特定Segment。
- 这种类型的锁定机制被称为 Segment-Locking 或 Bucket-Locking。
- 在 ConcurrentHashMap 中,一次执行 16 个更新操作。
- ConcurrentHashMap 中不可能插入空值。
Here are the ConcurrentHashMap construction.
这是 ConcurrentHashMap 的构造。
ConcurrentHashMap m=new ConcurrentHashMap();:Creates a new, empty map with a default initial capacity (16), load factor (0.75) and concurrencyLevel (16).
ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity);:Creates a new, empty map with the specified initial capacity, and with default load factor (0.75) and concurrencyLevel (16).
ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity, float loadFactor);: Creates a new, empty map with the specified initial capacity and load factor and with the default concurrencyLevel (16).
ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel);:Creates a new, empty map with the specified initial capacity, load factor and concurrency level.
ConcurrentHashMap m=new ConcurrentHashMap(Map m);:Creates a new map with the same mappings as the given map.
ConcurrentHashMap m=new ConcurrentHashMap();:创建一个新的空映射,默认初始容量 (16)、负载因子 (0.75) 和 concurrencyLevel (16)。
ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity);:创建一个具有指定初始容量、默认负载因子 (0.75) 和 concurrencyLevel (16) 的新的空映射。
ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity, float loadFactor);:使用指定的初始容量和负载因子以及默认的 concurrencyLevel (16) 创建一个新的空映射。
ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel);:使用指定的初始容量、负载因子和并发级别创建一个新的空映射。
ConcurrentHashMap m=new ConcurrentHashMap(Map m);:创建一个与给定映射具有相同映射关系的新映射。
ConcurretHashMap has one method named is putIfAbsent();That method is prevent to store the duplicate key please refer the below example.
ConcurretHashMap 有一个名为putIfAbsent() 的方法;该方法是防止存储重复键请参考下面的例子。
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);
}
}