安全地迭代多线程访问的ConcurrentHashMap

我有一个ConcurrentHashMap对象,它由多个线程共享来访问:

Map<String, MyConnection> myMap = new ConcurrentHashMap<String, MyConnection>();

类MyConnection包含到数据源的一些连接。

在稍后阶段,我需要迭代ConcurrentHashMap,调用MyConnection.close()方法并将其从Map中删除。 像这样的东西:

for(String key : myMap.ketSet()) {
    MyConnection connection = myMap.get(key);
    connection.close();
    myMap.remove(key);
}

但是,myMap由多个线程共享,可以同时从ConcurrentHashMap中添加或删除。

我如何确保上面的for循环可以线程安全地运行? 没有要求循环必须删除地图中的所有条目。 循环只需要在调用myMap.keySet()时删除所有元素。 任何后续添加到地图的元素都不必删除。

显然,我可以锁定整个for循环,并防止其他线程触摸地图,但我认为这不是性能高效的。

有人可以分享你的意见吗?

编辑1 :这个怎么样? 这个线程安全吗?

for(MyConnection connection : myMap.values()) {
    connection.close();
    myMap.remove(connection.getId());
}

每个连接对象都有一个ID,这也是该条目的关键。


您的方法当前不安全,因为您的connection可能为null (如果另一个线程在迭代时删除它),则可能会抛出NullPointerException。 只需添加一个空检查,并且您的方法是正确且线程安全的。

如果你关心性能,你可能只需要遍历map.values()并以这种方式去除变量,从而为每次迭代节省两次地图查找:

//the following code has not been compiled, and may be incorrect
Iterator<MyConnection> it = myMap.values().iterator();
while(it.hasNext())
{
    MyConnection c = it.next();
    if (c != null)
    {
        c.close();
    }
    it.remove();
}

迭代器/循环你提交的方式不是线程安全的,因为你没有迭代最新的地图。 但这不是你关心的问题,因为你只是从hashmap中删除一个元素 - 而且这个线程是安全的(由于ConcurrentHashMap)。 不需要锁定或同步它是没有意义的。

你的迭代都可以,因为你只能删除它,而你写道:

循环只需要在调用myMap.keySet()时删除所有元素。

你的代码很好。 您可能需要检查您的连接在关闭之前是否为空(如建议)

链接地址: http://www.djcxy.com/p/91919.html

上一篇: Safely iterate an ConcurrentHashMap that is accessed by multiple thread

下一篇: Modifying values in ConcurrentHashMap