解决ConcurrentModificationException,并证明线程安全容器的单步原子性
先看代码:
import java.util.HashMap;
import java.util.Map;
public class Mian {
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("1","炉石传说");
map.put("2","王者");
map.put("3","王者荣耀");
map.put("4","LOL");
map.put("5","英雄联盟");
for(Map.Entry<String,String> et:map.entrySet()){
if(et.getValue().length()==2){
map.remove(et.getKey());
}
}
for(Map.Entry<String,String> et:map.entrySet()){
System.out.println(et.getKey()+":"+et.getValue());
}
}
}
从map集合中去除,map的Value长度大于2的值 ,这种情况下执行结果如下:
对集合遍历的同时,又进行修改就会报上述错误,为解决上述问题,有以下方法:
1.使用索引来删除元素,不过不推荐
2.使用迭代器Iterator进行遍历:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class Mian {
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("1","炉石传说");
map.put("2","王者");
map.put("3","王者荣耀");
map.put("4","LOL");
map.put("5","英雄联盟");
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()){
if(iterator.next().getValue().length()==2){
iterator.remove();
}
}
for(Map.Entry<String,String> et:map.entrySet()){
System.out.println(et.getKey()+":"+et.getValue());
}
}
}
执行结果:
达到我们的目的;
3.使用线程安全的ConcurrentHashMap,或者ConcurrentSkipListMap
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Mian {
public static void main(String[] args) {
Map<String, String> map = new ConcurrentHashMap<String, String>();
map.put("1", "炉石传说");
map.put("2", "王者");
map.put("3", "王者荣耀");
map.put("4", "LOL");
map.put("5", "英雄联盟");
for(Map.Entry<String,String> et:map.entrySet()){
if(et.getValue().length()==2){
map.remove(et.getKey());
}
}
for (Map.Entry<String, String> et : map.entrySet()) {
System.out.println(et.getKey() + ":" + et.getValue());
}
}
}
执行结果:
当有多个线程同时向map中添加元素时,并且当map的长度小于5时,就不在添加,代码如下:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 此实验用来证明线程安全容器的单步原子性
*/
public class Dome {
public static void main(String[] args) throws InterruptedException {
Map<String, String> map = new ConcurrentHashMap<String, String>();
map.put("1","炉石传说");
map.put("2","王者");
map.put("3","王者荣耀");
map.put("4","LOL");
Thread thread01 = new Thread(() -> {
if (map.size() < 5) {
map.put("5","英雄联盟");
}
}, "线程一");
Thread thread02 = new Thread(() -> {
if (map.size() < 5) {
map.put("5X","英雄联盟X");
}
}, "线程二");
thread01.start();
thread02.start();
Thread.sleep(2000);
map.entrySet().forEach(o -> {
System.out.println(o.getKey() + ":" + o.getValue());
});
}
}
大多数情况下执行结果为:
以上两种情况
单也有极少数情况下会出现以下情况:
即两个线程同时成功,这说明即使是线程安全的集合也只能保证单步原子性,当size,和put同时进行时就不能保证线程安全了,此外解决解决ConcurrentModificationException还可对集合下标进行遍历的方式.
上述文章如有错误请麻烦指出,共同进步