zoukankan      html  css  js  c++  java
  • java.util.ConcurrentModificationException异常原因及解决方法

    今天在做一个很简单的Java练习题的时候遇到这个问题。

    题目:一对兔子在出生第三个月的时候开始,每个月会生一对小兔子。当小兔子在它们第三个月的时候,同理。问:每个月的兔子总数。

    这是一个很简单的题,前6个月的兔子数量是,1,1,2,3,5,8.斐波拉契数列。按这个规律就可以得出结果。但是我是用创建对象的方法来做。

    代码:

    public class Main {
    
        private static List<Rabbit> mList = new CopyOnWriteArrayList<>();
    
        public static void main(String[] args) {
            Rabbit r1 = new Rabbit(0);
            mList.add(r1);
            for (int i = 0; i < 10; i++) {
                for(Rabbit r:mList){
                    if (r.getAge()>=2){
                        mList.add(r.born());
                    }
                    r.grow();
                }
                System.out.println("第"+i+"个月, 兔子数量:"+mList.size()+"对");
            }
        }
    
    
    }
    public class Rabbit {
    
        private int age ;//以月为单位
    
        public Rabbit(int age) {
            this.age = age;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Rabbit born(){
            if (age>=2){
               return new Rabbit(1);
            }
            return null;
        }
    
        public void grow(){
            setAge(age+=1);
        }
    
        @Override
        public String toString() {
            return "[年龄:"+age+"个月]";
        }
    }

    最开始我没有用CopyOnWriteArrayList这个类,我就用的ArrayList.然后就报题目中的异常了。然后网上一查,才知道,ArrayList在读的时候,不能同时进行增删。可以从源码中去查看。然后CopyOnWriteArrayList这个类,是在写时拷贝,也就是如果需要对CopyOnWriteArrayList的内容进行改变,首先会拷贝一份新的List并且在新的List上进行修改,最后将原List的引用指向新的List。使用CopyOnWriteArrayList可以线程安全地遍历,因为如果另外一个线程在遍历的时候修改List的话,实际上会拷贝出一个新的List上修改,而不影响当前正在被遍历的List。

    如果是HashMap使用“ConcurrentHashMap”替换HashMap,ConcurrentHashMap会自己检查修改操作,对其加锁,也可针对插入操作。

    ps:这个小题目,我在兔子年龄上花了不少时间,把我自己搞晕了。实际上是在它们第2个月完,第3个月开始就开始生产了。

  • 相关阅读:
    PowerDesigner应用02 逆向工程之导出PDM文件前过滤元数据(表、视图、存储过程等)
    PowerDesigner应用01 逆向工程之配置数据源并导出PDM文件
    CLR查找和加载程序集的方式(二) 流程图
    CLR查找和加载程序集的方式(一)
    C#控制台程序入口函数 Main(string[] args) 参数详解
    INotifyPropertyChanged 接口 CallerMemberName属性
    INotifyPropertyChanged 接口
    SQL Server 中执行Shell脚本计算本地文件的内容大小
    统计一个数据库中,无记录的表的sql语句
    SQL 性能优化 总结
  • 原文地址:https://www.cnblogs.com/jdhdevelop/p/11170032.html
Copyright © 2011-2022 走看看