Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java从ConcurrentHashMap中删除特定项_Java_Thread Safety_Java.util.concurrent_Concurrenthashmap - Fatal编程技术网

Java从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

使用remove()方法可以吗?我读过一篇文章,其中提到没有将同步添加到remove方法中。如何从ConcurrentHashMap中正确删除特定的项目

示例代码:

    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和隔离级别进行模拟。希望你明白我的意思。