Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/11.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_Multithreading - Fatal编程技术网

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

Java 安全地迭代多线程访问的ConcurrentHashMap,java,multithreading,Java,Multithreading,我有一个ConcurrentHashMap对象,由多个线程共享以访问: Map<String, MyConnection> myMap = new ConcurrentHashMap<String, MyConnection>(); 但是,myMap由多个线程共享,这些线程可以同时从ConcurrentHashMap中添加、删除 如何确保上面的for循环运行时线程安全?不要求循环必须删除映射中的所有条目。循环只需要在调用myMap.keySet()时删除所有元素。添加到

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

Map<String, MyConnection> myMap = new ConcurrentHashMap<String, MyConnection>();
但是,myMap由多个线程共享,这些线程可以同时从ConcurrentHashMap中添加、删除

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

显然,我可以锁定整个for循环,并防止其他线程接触映射,但我认为这并不能提高性能

有人能分享你的观点吗

EDIT1:这个怎么样?这个线安全吗

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

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

迭代器/循环您呈现的方式不是线程安全的,因为您没有迭代最新的映射。但这不是您所关心的,因为您只是从hashmap中删除一个元素——这是线程安全的(由于ConcurrentHashMap)。不需要设置锁或同步,这毫无意义

您的两个迭代都可以,因为您只删除了它,并且您写了:

循环一次只需要删除所有元素 调用myMap.keySet()


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

正确的方法是使用remove的返回值:

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

这很可能是以下内容的重复。简而言之,您可以使用迭代器,并且需要在此迭代器(而不是映射)上调用remove方法:@eckes我不同意。这个问题的公认答案是,在ConcurrentHashMap上迭代通常是安全的,对于给定的值“通常”是正确的。但是凯文的使用是不安全的,所以他提出一个单独的问题是正确的。谢谢你的回答。我当然从埃克斯提到的另一个问题中得到了一些提示。我的要求很简单。我所需要的只是安全地删除对象并使地图保持有效状态。如果另一个线程在另一个线程循环时添加了一个新条目,则可以将新添加的条目保留在映射中。如果是,上面的回路安全吗?或者我必须使用迭代器,正如在另一个问题中提到的那样?第二个问题很好。
for(String key : myMap.ketSet()) {
    MyConnection connection = myMap.remove(key);
    if (connection != null)
        connection.close();
}