Java从ConcurrentHashMap中删除特定项
使用remove()方法可以吗?我读过一篇文章,其中提到没有将同步添加到remove方法中。如何从ConcurrentHashMap中正确删除特定的项目 示例代码:Java从ConcurrentHashMap中删除特定项,java,thread-safety,java.util.concurrent,concurrenthashmap,Java,Thread Safety,Java.util.concurrent,Concurrenthashmap,使用remove()方法可以吗?我读过一篇文章,其中提到没有将同步添加到remove方法中。如何从ConcurrentHashMap中正确删除特定的项目 示例代码: ConcurrentHashMap<String,Integer> storage = new ConcurrentHashMap<String,Integer>(); storage.put("First", 1); storage.put("Second", 2); sto
ConcurrentHashMap<String,Integer> storage = new ConcurrentHashMap<String,Integer>();
storage.put("First", 1);
storage.put("Second", 2);
storage.put("Third",3);
//Is this the proper way of removing a specific item from a tread-safe collection?
storage.remove("First");
for (Entry<String, Integer> entry : storage.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// ...
System.out.println(key + " " + value);
}
ConcurrentHashMap存储=新建ConcurrentHashMap();
储存。放置(“第一”,1);
储存。放置(“第二”,2);
储存。放置(“第三”,3);
//这是从胎面安全收藏中删除特定项目的正确方法吗?
储存。移除(“第一”);
for(条目:storage.entrySet()){
String key=entry.getKey();
对象值=entry.getValue();
// ...
System.out.println(键+“”+值);
}
删除方法在锁上进行同步。实际上,在检查ConcurrentHashMap#remove()
的代码时,会调用获取锁的lock
方法:
public V remove(Object key) {
int hash = hash(key.hashCode());
return segmentFor(hash).remove(key, hash, null);
}
其中,ConcurrentHashMap.Segment#remove(key,hash,null)
定义为:
V remove(Object key, int hash, Object value) {
lock();
try {
...
请注意描述:
检索操作(包括get
)通常不会阻塞,因此可能与更新操作(包括put
和remove
)重叠。检索反映了最近完成的更新操作在开始时的结果。对于聚合操作,如putAll
和clear
,并发检索可能只反映插入或删除某些条目。类似地,迭代器和枚举返回反映哈希表在迭代器/枚举创建时或创建之后某个点的状态的元素。它们不会抛出ConcurrentModificationException
。但是,迭代器设计为一次只能由一个线程使用
应完成以下工作:
Iterator<Map.Entry<String, Integer>> iterator = storage.entrySet().iterator();
while(iterator.hasNext())
{
Map.Entry<String, Integer> entry = iterator.next();
if(entry.getKey().equals("First"))
{
iterator.remove();
}
}
Iterator Iterator=storage.entrySet().Iterator();
while(iterator.hasNext())
{
Map.Entry=iterator.next();
if(entry.getKey().equals(“First”))
{
iterator.remove();
}
}
参考:您可以在入口集上直接使用removeIf:
map.entrySet().removeIf( entry -> .. some condicion on entry )
请注意,Java 8中有一个错误仅从Java 9中修复()。“我读过一篇文章,说同步没有添加到删除方法中。”那篇文章是关于Java 5、6、7或8的时代写的吗?也许它是用一个旧的Java版本写的,希望这个链接能起作用。他说:“由于像put()、remove()、putAll()或clear()这样的更新操作没有同步,请阅读更多:@peter.petrov-像我在代码示例中那样在ConcurrentHashMap上调用remove方法是可以的,对吗?”?线程安全不应该是一个问题?不完全确定。我想,本文的意思是:在
remove
中,并不是整个表都被锁定,而是只锁定了其中的一个给定部分(如manouti发布的代码所示)。至少这就是我读这篇文章的方式和它的意义。所以这完全取决于您的并发场景。不确定,如果我要肯定地回答这个问题,需要自己从头开始研究。@peter.petrov-Hm,那么我如何从concurrecthashmap中删除特定项?我在代码示例中使用的删除方法也可以,对吗?我不必担心线程安全?是的,它很好。它是线程安全的,因为使用它不需要锁定,并且不会发生ConcurrentModificationException
。同样:作者只是说,删除在整个表对象上不同步。至少我是这样读的。@peter.petrov-只是为了确认一下,我会放弃这种情况,我在上面的示例代码中调用它的方式很好,我不必担心线程安全性?@spudone是的,这并不矛盾。它们是线程安全的,这里讨论的是一致性级别(参见javadoc mahouti发布的文章)。因此,例如,我猜在一些复杂的场景中,get
操作可能会看到表中的某个东西已经从表中删除了:)这就是我阅读这些内容的方式。考虑使用RDBMS和隔离级别进行模拟。希望你明白我的意思。