精华内容
下载资源
问答
  • 并发修改异常解决办法
    2022-01-26 20:36:24

    如何解决并发修改异常

    解决方法:

    1.采用列表迭代器解决,添加元素的时候,必须使用列表迭代器的添加元素的方法。特点:在当前元素的后面添加指定元素

    2.采用普通for循环的方式遍历集合,并添加元素。特点:在集合元素的最后添加指定的元素

    3.采用CopyOnWriteArrayList集合实现,它自身已经规避了并发修改异常。特点:在集合元素的最后添加指定的元素

    更多相关内容
  • 今天小编就为大家分享一篇关于collection集合体系与并发修改异常解决方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
  • 问题引出:当我们从集合中找出某个元素并删除的时候可能出现一种并发修改异常问题, 如下图所示: 集合的哪些遍历存在问题? 1、迭代器遍历集合且直接用集合删除元素的时候可能出现。 2、增强for循环遍历集合且直接...

    从集合中的一批元素中找出某些数据并删除,如何操作?是否存在问题呢 ?
    问题引出:当我们从集合中找出某个元素并删除的时候可能出现一种并发修改异常问题, 如下图所示:
    在这里插入图片描述集合的哪些遍历存在问题?

    1、迭代器遍历集合且直接用集合删除元素的时候可能出现。
    2、增强for循环遍历集合且直接用集合删除元素的时候可能出现。
    

    集合的哪种遍历且删除元素不出问题

    1、迭代器遍历集合但是用迭代器自己的删除方法操作可以解决。
    2、使用for循环遍历并删除元素不会存在这个问题。
    

    验证如下:
    1、迭代器遍历集合且直接用集合删除元素的时候可能出现并发修改异常,但是用迭代器自己的删除方法操作可以解决

    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class TestDemo {
        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<>();
            list.add("黑马");
            list.add("Java");
            list.add("Java");
            list.add("赵敏");
            list.add("赵敏");
            list.add("速速");
            System.out.println(list);
    
            // 删除全部的java信息
            // [黑马, Java, Java, 赵敏, 赵敏, 速速]
            //         it:出错的原因在于用list.remove("Java")进行删除第一个Java后,it向后移动,直接指到赵敏的位置
            // 没有进行完全删除, 而使用迭代器自带的it.remove()在进行并发操作的时候进行删除向后退一个
            // 1. 使用迭代器进行删除
            Iterator<String> it = list.iterator();
            while (it.hasNext()){
                String ele = it.next();
                if("Java".equals(ele)){
                    // 删除Java
                    //list.remove(ele);  // ConcurrentModificationException并发修改异常
                    it.remove();  // 使用迭代器自在的删除可以成功, 因为执行成功后会自动进行减1操作
                }
            }
            System.out.println(list);
        }
    }
    

    在这里插入图片描述
    2、增强for循环/foreach/lambda遍历集合且直接用集合删除元素的时候可能出现

    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class TestDemo {
        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<>();
            list.add("黑马");
            list.add("Java");
            list.add("Java");
            list.add("赵敏");
            list.add("赵敏");
            list.add("速速");
            System.out.println(list);
    
            // 2. foreach、增强for循环删除(会出现问题,这种无法解决的,foreach不能边遍历边删除,会出bug)
            for(String s : list){
                if("Java".equals(s)){
                    list.remove(s);  // ConcurrentModificationException
                }
            }
    
            // 3. lambda表达式(会出现问题,这种无法解决的,Lambda遍历不能边遍历边删除,会出bug)
            list.forEach(s -> {
                if("Java".equals(s)){
                    list.remove(s); // ConcurrentModificationException
                }
            });
        }
    }
    
    

    在这里插入图片描述3、使用for循环遍历并删除元素可以解决并发修改异常问题
    方法1:指针回退
    在这里插入图片描述方法2:倒数遍历删除
    在这里插入图片描述

    展开全文
  • 并发修改异常 (ConcurrntModificationException)原理及其解决方案 问题演示 小伙伴们可以运行一下 遍历集合元素的过程中删除元素 public void testConcurrentModifyException() throws InterruptedException { List...

    并发修改异常 (ConcurrntModificationException)原理及其解决方案

    问题演示

    小伙伴们可以运行一下

    遍历集合元素的过程中删除元素
    public void testConcurrentModifyException() throws InterruptedException {
            List<Integer> list = new ArrayList<>();
            list.add(1);
            list.add(1);
            for(Integer num : list){
                list.remove(0);
            }
        }
    
    第二种方式
    1.创建10个线程分别共享变量ArrayList添加元素,
    2.主线程对ArrayList进行遍历
    运行过程中就会抛出ConcurrentModificationException
    public void testConcurrentModifyException() throws InterruptedException {
            List<Integer> list = new ArrayList<>();
            for(int i = 0;i < 10;i++){
                new Thread(()-> {
                    for(int j = 0;j < 100;j++) {
                        list.add(j);
                    }
                },"A + i").start();
            }
            for(Integer tmp:list){}
            Thread.sleep(20000);
            System.out.println(list.size());
        }
    
    

    其实这两种方式触发ConcurrentModificationException的通过相同的方式,看似一个单线程,一个多线程

    我在这个地方简述一下这个异常出发的大致原理;
    1.首先ArrayList类中有一个共享变量modCount,我们每操作一次集合这个变量都会进行加一操作(增,删,改,不包含查询)
    2. 我们在开始遍历集合元素的时候,会记录此时的modCount作为expectedModCount,每次遍历一个元素的的时候都会检查,这两个参数是否相等;如果不想等就会抛出ConcurrentModifyException

    第一种方式解决方式是比较简单的

    下面是代码示例:

    public void testSolveModificationException () {
            List<Integer> list = new ArrayList<>();
            list.add(1);
            list.add(1);
            Iterator<Integer> it = list.iterator();
            while(it.hasNext()) {
                Integer num = it.next();
                System.out.println(num);
                it.remove();
            }
            System.out.println("size = " + list.size());
        }
    

    为什么这个方法没有抛出并发修改异常?大概浏览一下代码,迭代器删除元素是,调用也是ArrrayList对象的remove, 此时成员变量modCount进行++操作,此时迭代器用modCount对给expectModCount进行赋值,所以通过这个方式不会抛出并发修改异常

    第二种情况的解决方式:

    我们可以分析思路:

    出现并发修改异常,多个线程对共享变量ArrayList并发进行读写导致的,一般需要用到锁相关的知识了,我们是无法直接对ArrayList进行加锁的

    解决方式

    1:使用线程安全的集合(Vector),

    这是从jdk 1.1开始就存在的集合,其实也会抛并发修改异常,跟进了一下源码,所有的方法都加了synchronized,为什么还会出现异常呢?这是因为 遍历元素时,各个元素都是独立的释放获取锁,这也造成 增加,遍历元素,交替的获取锁的所以此时调用checkForComodification也会抛ConcurrentModificationException;

    2.使用jdk提供的提供的工具类,

    但是下面这种方式,并不能解决并发并发修改异常,小伙伴可以多实验几次,就会复现;其实jdk工具类的实现的基本逻辑是基于装饰的设计模式;装饰之后是实现类SynchronizedRandomAccessList;其实使用这种方式,只是增,删,改,编程进行了加锁,对于遍历是没有加锁的 源码了只有 Must be manually synched by user 大概意思是遍历需要用户自己实现同步;
    虽然是一个大坑,但是我们开发过程中很少使用,也就很少遇到了;

    List list = Collections.synchronizedList(new ArrayList<>())

    public void testConcurrentModifyExceptionV2() throws InterruptedException {
            //List<Integer> list = new ArrayList<>();
            List<Integer> list = Collections.synchronizedList(new ArrayList<>());
            for(int i = 0;i < 10;i++){
                new Thread(()-> {
                    for(int j = 0;j < 100;j++) {
                        list.add(j);
                    }
                },"A + i").start();
            }
            int cnt = 0;
            for(Integer tmp:list){
                cnt++;
            }
            System.out.println(cnt);
            Thread.sleep(20000);
            System.out.println(list.size());
        }
    

    第三种方式 CopyOnWriteArrayList,传说中的写时复制,基本思想有点类似于读写分离,随后会针对CopyOnWriteArrayList写一个文章,这里就不再介绍了

    欢迎小伙们多多指正,共同进步;

    展开全文
  • 使用并发集合替换掉原集合可以实现并发修改安全。 原集合 并发集合 注意 HashMap ConcurrentHashMap<K,V> Hashtable虽然线程安全但不支持并发修改 LinkedHashMap ConcurrentSkipListMap<K,V>...

    java.util.ConcurrentModificationException异常

    使用并发集合替换掉原集合可以实现并发修改安全。

    原集合并发集合注意
    HashMapConcurrentHashMap<K,V>Hashtable虽然线程安全但不支持并发修改
    LinkedHashMapConcurrentSkipListMap<K,V>支持排序,且并发安全
    LinkedHashSetConcurrentSkipListSet支持排序,且不允许有重复元素
    QueueConcurrentLinkedQueue只能操作队列头
    DequeConcurrentLinkedDeque队头队尾都可操作
    ArrayListCopyOnWriteArrayList支持并发安全
    HashSetCopyOnWriteArraySet支持并发安全

    展开全文
  • 05Java集合-6. 并发修改异常的产生原因和解决办法*
  • HashMap并发修改异常解决办法

    千次阅读 2017-04-20 19:18:56
    我在循环读取hashmap里的内容时,在循环中又在另外一个线程对hashmap...翻译过来就是并发修改异常,上网找了下资料,解决方法如下: 调用HashMap的reomve方法时会出现 java.util.ConcurrentModificationExcepti
  • Java list集合并发修改异常处理办法
  • iterator并发修改异常 并发修改异常 ​ 在用迭代器遍历容器的时候,试图去修改容器中的元素,可能会引起并发修改异常(遍历的时候,相当于一个指针从0索引开始移动,当试图修改某个数据时,系统无法去操作这个指针) /...
  • 文章目录 异常名称: 问题描述 举例说明-代码 原因分析: 解决方案: 特例: 异常名称: ConcurrentModificationException并发修改异常 问题描述 当调用了集合本身增删过程中出现并发修改异常: 当我们在遍历实现了...
  • 目录 并发修改异常简介 异常展示 异常原因 ... 并发修改异常的原因是:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。 场景:当我们在对集合进行迭代遍历操作的时候,如果同
  • 并发修改异常

    2019-06-21 16:13:29
    ConcurrentModificationException: 并发修改异常:使用迭代器遍历集合的时候修改了集合的长度
  • 并发修改异常原理及原因

    千次阅读 2022-03-01 19:38:57
    并发修改异常(迭代器在使用的时候,尽量不要使得集合的长度发生变化,也就是不能在迭代器中增删,但是改变位置元素的内容是可以的) 通俗的讲: 迭代器在一个类里面遍历第二次集合,也会有这个并发异常出现 for增强型和...
  • 【HashMap并发修改异常

    千次阅读 多人点赞 2021-11-28 22:42:52
    我是廖志伟,一名Java开发工程师、幕后...文章目录HashMap并发修改异常使用HashTable使用工具类使用写时复制(CopyOnWrite)使用ConcurrentHashMap 本文的大概内容: HashMap并发修改异常 HashMap实际使用过程中会出.
  • 什么是并发修改异常

    2022-03-11 15:40:49
    1.并发修改异常的原因是什么? 原因: 使用迭代器遍历集合元素时,又通过集合对象本身调用集合的方法,修改了...2.为什么使用迭代器遍历Collection集合时,使用集合对象的remove方法删除倒数第二个元素,不报并发修改异常?
  • 很多人会写出以下代码,但是运行则会抛出异常。List list = new ArrayList<>();list.add("a");list.add("b");list.add("c");for (String str : list) {if ("a".equals(str)) {list.remove("a");}}复制代码会出...
  • List&并发修改异常

    2021-09-08 23:11:33
    List List集合的特有方法 void add(int index , E element)在此集合中的指定位置插入指定的... 并发修改异常 每次通过迭代器调用next方法的时候都会判断预期修改次数和实际修改次数是否相同,在调用add方法
  • HashMap并发修改异常
  • 一、ConcurrentModificationException【并发修改异常】 产生原因:迭代器遍历过程中,使用集合对象对当前集合元素进行修改操作 错误代码实例: package com.tlc.gather; import java.util.ArrayList; import ...
  • 2.异常现象 3.导致原因 4.解决方式 二.集合类不安全之HashSet 1.示例代码 2.异常现象 3.解决方式 ①:Collections.synchronizedSet(); ②:new CopyOnWriteArraySet(); 三.集合类不安全之Map 1.代码演示 ...
  • 使用普通for循环不会发生并发修改异常,但是会导致删除不完全,这是因为在删除的时候,会把后面的数据往前移动,可以使用倒序遍历解决这个问题。当然,在使用iterator也不会发生问题(最好)。 为什么使用iterator...
  • 并发修改异常一 什么是并发修改异常...= expectedModCount的原因三解决并发修改异常的方案1使用 Vector(同步的)为什么使用Vector2 使用Collections.synchronizedListCollections.synchr
  • HashSet并发修改异常
  • 并发修改异常解决办法: 1.采用for循环的方式 List list = new ArrayList(); list.add("Hello"); list.add("World"); list.add("Java"); for(int i=0;i 2.采用LIstIterator列表迭代器 List list = new ArrayList();...
  • Iterator接口定义了以下四种方法。boolean hasNext():如果集合还没遍历完就返回true。Object next():返回集合里的下一个元素。void remove():删除集合里上一次next方法返回的元素。void forEachRemaining...
  • modCount的含义、迭代器所包含的方法、为什么会发生并发修改异常都将会在这篇文章中进行说明。 引入 这是一个并发修改异常的示例,它使用了迭代器iterator来获取元素,同时使用ArrayList自身的remove方法移除元素...
  • 当我们从集合中找出某个元素并删除的时候可能出现一种并发修改异常问题。 一、哪些问题遍历存在问题? 迭代器遍历过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改至不...
  • 并发修改异常原理与解决方法

    千次阅读 2017-06-20 17:22:04
    什么是并发修改异常: 当我们在遍历实现了collection接口与iterator接口的集合时(List、Set、Map), 我们可以通过遍历索引也可以通过迭代器进行遍历。在我们使用迭代器进行遍历集合的时候,会获取到当前集合的迭代...
  • 并发修改异常产生的原因及解决方案 A:案例演示 需求:我有一个集合,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。 List list = new ArrayList(); list.add("a...
  • 1:使用增强for循环(出现并发修改异常) package com.concom.list; import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput; import java.util.*; import java.util.stream.Collectors; import java.util....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 157,507
精华内容 63,002
热门标签
关键字:

并发修改异常解决办法