安全地迭代多线程访问的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