java.util.ConcurrentModificationException异常原因及解决方法

Wesley13
• 阅读 802

今天在做一个很简单的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个月开始就开始生产了。

点赞
收藏
评论区
推荐文章
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java经典50题
JAVA基础编程练习50题本文对50道经典的java程序题进行详细解说,对于初学者可以跳过一些逻辑性太强的题目,比如第一题用到了方法的递归,初学者可能不理解,最好先看那些有if、for、while可以简单解决的程序题!但是,对于比较深入学习过的同学,还是希望可以一口气就看完,这是比较全面思维锻炼!【程序1】题目:古典问题:有一对兔子,从
Wesley13 Wesley13
3年前
java基础编程练习题
1、題目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?123456711235813这就是斐波那契数列(Fibonaccisequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Le
CuterCorley CuterCorley
3年前
C语言基础习题50例(三)11-15
你们看出神马了吗(\\^_\^\)习题11有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少实现思路:从第1个月起,兔子对数分别为1、1、2、3、5、8、13、21...,显然是斐波拉契数列。代码如下:cinclude<stdio.hintmai
Wesley13 Wesley13
3年前
Java面试不得不知的程序(二)
【程序1】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?斐波那契数列:前面相邻两项之和,构成了后一项通项公式注:此时a11,a21,ana(n1)a(n2)(n3,n∈N\)通项公式的推导斐波那契数列:1、1
Stella981 Stella981
3年前
Python递归函数、匿名函数、过滤函数
递归函数Python对递归的深度有限制,超过即会报错。所以一定一要注意跳出条件。斐波拉契数列一个数列,第一个数是1,第二个数也是1,从第三个数开始,每一个数是前两个数之和公式:f(1)1,f(2)1,f(3)f(1)f(2),...,f(n)f(n2)f(n1)
Stella981 Stella981
3年前
No operations allowed after statement closed.
之所以会出现这个异常,是因为Mysql在5以后针对超长时间DB连接做了一个处理,那就是如果一个DB连接在无任何操作情况下过了8个小时后,Mysql会自动把这个连接关闭。所以使用连接池的时候虽然连接对象还在但是链接数据库的时候会一直报这个异常。解决方法很简单在Mysql的官方网站上就可以找到。有两个方法第一种是在DB连接字符串后面加一个参数。
Stella981 Stella981
3年前
Hibernate纯sql查询结果和该sql在数据库直接查询结果不一致
问题:今天在做一个查询的时候发现一个问题,我先在数据库实现了我需要的sql,然后我在代码中代码:selectdistinctd.id,d.name,COALESCE(c.count_num,0),COALESCE(c.count_fix,0),COALESCE(c
Wesley13 Wesley13
3年前
MySQL 5.7查询sys.schema_redundant_indexes居然慢如蜗牛...
大家好,我是知数堂SQL优化班老师网名:骑龟的兔子作为DBA经常使用SYS视图,但是如下情况。查询mysql自己创建好的sys系统视图,超过70秒还没结果,超时了。一般情况下,不会出现问题,但是,如本案例,表很多的时候就会出现问题selectcount()frominformation_
Stella981 Stella981
3年前
Android开发——发布第三方库到JitPack上
前言:看到大神们的写的第三方控件,比较好用,我们使用的时候直接是在gradle上加上代码就可以使用了,现在到我们写了一个第三方控件,想要别人使用的时候也是直接在gradle加上相关的代码就可以用了,我们该如何操作呢?答案很简单,就是在JitPack网站上发布我们的库就可以正文:1.创建一个moudle这里其实就是相当于