Pra*_*een 56 java concurrenthashmap
ConcurrentHashMap
在Java中有什么用?它有什么好处?它是如何工作的?示例代码也很有用.
dan*_*ben 71
关键是提供HashMap
线程安全的实现.多个线程可以读取和写入它,而不会接收到过时或损坏的数据. ConcurrentHashMap
提供自己的同步,因此您不必显式同步对它的访问.
另一个特性ConcurrentHashMap
是它提供了putIfAbsent
方法,如果指定的键不存在,它将以原子方式添加映射.请考虑以下代码:
ConcurrentHashMap<String, Integer> myMap = new ConcurrentHashMap<String, Integer>();
// some stuff
if (!myMap.contains("key")) {
myMap.put("key", 3);
}
Run Code Online (Sandbox Code Playgroud)
此代码不是线程安全的,因为另一个线程可以"key"
在调用contains
和调用之间添加映射put
.正确的实施将是:
myMap.putIfAbsent("key", 3);
Run Code Online (Sandbox Code Playgroud)
Tha*_*var 30
ConcurrentHashMap
允许并发访问地图.HashTables也提供对地图的同步访问,但您的整个地图都被锁定以执行任何操作.
ConcurrentHashMap背后的逻辑是your entire table is not getting locked
,但只有部分[ segments
].每个细分都管理自己的HashTable.锁定仅适用于更新.在检索的情况下,它允许完全并发.
让我们将四个线程同时在一个容量为32的映射上工作,该表被分成四个段,每个段管理一个容量哈希表.该集合默认维护一个包含16个段的列表,每个段用于保护(或锁定)地图的单个存储桶.
这实际上意味着16个线程可以一次修改集合.使用可选的concurrencyLevel构造函数参数可以增加此并发级别.
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel)
Run Code Online (Sandbox Code Playgroud)
正如另一个答案所述,ConcurrentHashMap提供了putIfAbsent()
类似于put的新方法,除非键存在时不会覆盖该值.
private static Map<String,String> aMap =new ConcurrentHashMap<String,String>();
if(!aMap.contains("key"))
aMap.put("key","value");
Run Code Online (Sandbox Code Playgroud)
新方法也更快,因为它避免double traversing
了如上所述.contains
方法必须定位段并迭代表以找到密钥,并且方法put
必须再次遍历桶并放置密钥.
Aff*_*ffe 12
实际上,最大的功能区别在于,当您使用它时,当其他人更改它时,它不会抛出异常和/或最终损坏.
对于常规集合,如果另一个线程在您访问它时(通过迭代器)添加或删除元素,则会抛出异常.ConcurrentHashMap允许他们进行更改并且不会停止您的线程.
请注意,它不会对从一个线程到另一个线程的更改的时间点可见性做出任何形式的同步保证或承诺.(它有点像读取提交的数据库隔离,而不是同步映射,其行为更像是可序列化的数据库隔离.(旧学校行锁定SQL可序列化,而不是Oracle-ish multiversion序列化:))
我所知道的最常见的用途是在App Server环境中缓存不可变的派生信息,其中许多线程可能正在访问同一个东西,并且如果两个碰巧计算相同的缓存值并将它放两次因为它们交错并不重要等等(例如,它在Spring WebMVC框架内广泛使用,用于保存运行时派生的配置,如从URL到Handler方法的映射.)
归档时间: |
|
查看次数: |
53139 次 |
最近记录: |