首页 > 编程语言 >JavaSE---Fail-Fast

JavaSE---Fail-Fast

时间:2024-09-23 16:14:54浏览次数:10  
标签:index int elementData list --- modCount Fail JavaSE size

总结

  主要用于集合类中,以确保 在遍历集合时如果集合本身被修改,则会立即抛出ConcurrentModificationException异常。

原理

  • 内部计数器:每个集合对象都有一个内部计数器,称为modCount(modification count)。每当集合结构被修改(比如添加或删除元素),这个计数器就会增加。
  • 迭代器检查:当通过迭代器遍历集合时,迭代器会在每次调用next()方法之前检查当前的modCount是否与创建迭代器时的expectedModCount相匹配。如果不匹配,说明集合已经被修改了,这时迭代器就会抛出ConcurrentModificationException

 

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {

        transient Object[] elementData;
        private int size;
        
        // add
        public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;                                                        // size ++
            return true;
        }

        private void ensureCapacityInternal(int minCapacity) {
            ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
        }

        private void ensureExplicitCapacity(int minCapacity) {
            modCount++;                                                                     // modCount++

            // overflow-conscious code
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }

        // remove
        public boolean remove(Object o) {
            if (o == null) {
                for (int index = 0; index < size; index++)
                    if (elementData[index] == null) {
                        fastRemove(index);
                        return true;
                    }
            } else {
                for (int index = 0; index < size; index++)
                    if (o.equals(elementData[index])) {
                        fastRemove(index);
                        return true;
                    }
            }
            return false;
        }

        private void fastRemove(int index) {
            modCount++;                                                                 // modCount++
            int numMoved = size - index - 1;
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index, numMoved);
            elementData[--size] = null; // clear to let GC do its work                  // --size
        }

        private class Itr implements Iterator<E> {
            int cursor;       // index of next element to return
            int lastRet = -1; // index of last element returned; -1 if no such
            int expectedModCount = modCount;

            public boolean hasNext() {
                return cursor != size;
            }

            @SuppressWarnings("unchecked")
            public E next() {
                checkForComodification();
                int i = cursor;
                if (i >= size)
                    throw new NoSuchElementException();
                Object[] elementData = this.elementData;
                if (i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i + 1;
                return (E) elementData[lastRet = i];
            }

            public void remove() {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();

                try {
                    this.remove(lastRet);
                    cursor = lastRet;
                    lastRet = -1;
                    expectedModCount = modCount;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }

            final void checkForComodification() {
                if (modCount != expectedModCount)                       // modCount与expectedModCount比较
                    throw new ConcurrentModificationException();
            }
        }
    }

  

示例

单线程

  当使用iterator遍历List & 使用List的remove,将会ConcurrentModificationException;

List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");
        list.add("Banana");
        
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String fruit = iterator.next();
            // 在遍历过程中修改集合
            if ("Banana".equals(fruit)) {
                list.remove(fruit);
            }
        }
        System.out.println(list);

  list的remove会修改modCount,导致modCount 与 expectedModCount不相等;

 

解决  

1、使用iterator遍历时,使用iterator的remove,将不会修改modCount;

2、多线程环境,使用线程安全集合类;

3、同步控制,保证只有一个线程能访问集合;

标签:index,int,elementData,list,---,modCount,Fail,JavaSE,size
From: https://www.cnblogs.com/anpeiyong/p/18427204

相关文章

  • 关于 2-SAT 的方案构造
    基本思想是按某种顺序为每一对未确定的\((a,\nega)\)确定一个合法的点并将其后代加入方案。如果本次选择了\(a\),其合法等价于之后选到的\(a\)的后代不会同时包含某个点对\((b,\negb)\)。其可以细分为:①之后选到的\(a\)的后代不包含先前已被加入到方案的点的反面,这里所说......
  • VR开发日志-VR开发环境搭建篇
    VR开发日志-VR开发环境搭建篇目录前言一、环境准备1.UE5安装2.下载开源插件VRExpansionPlugin3.下载安装VisualStudio二、基本设置&项目创建1.新建UE5项目2.按步骤点击创建​编辑3.创建成功后先关闭项目4.在项目文件根目录创建文件夹,命名为:Plugins5.把前面下载......
  • Stable Diffusion 使用详解(13)--- 3D纹理增强
    目录背景NormalMap描述原理使用心得例子描述原图参数设置底模​编辑正负相关性提示词其他参数controlnet效果还能做点啥调整效果背景实际上,在stablediffusion中,你获取发现很多controlnet其实功能有点类似,你都使用完一遍之后,会发现条条道路通罗马,有的......
  • 计算机专业选题推荐-基于python的协同过滤酒店推荐系统
    精彩专栏推荐订阅:在下方主页......
  • Codeforces Round 973 (Div.2) A-E题解
    CodeforcesRound973(Div.2)A-E题解比赛传送门A.Zhan'sBlender数学显然答案为\(\lceil\frac{n}{min(x,y)}\rceil\)。#include<bits/stdc++.h>usingnamespacestd;#definefffirst#definesssecond#definepbpush_back#defineall(u)u.begin(),u.en......
  • Paper Reading(2)-Audio Generation with Multiple Conditional Diffusion Model
    AudioGenerationwithMultipleConditionalDiffusionModel来源:http://export.arxiv.org/abs/2308.11940https://conditionaudiogen.github.io/conditionaudiogen/主要贡献:1)引入了一个新的任务,该任务可生成由文本和控制条件指导的音频,从而能够使用时间戳、音高轮廓和能量......
  • Paper Reading(1)-VarietySound: Timbre-Controllable Video to Sound Generation via U
    VarietySound:Timbre-ControllableVideotoSoundGenerationviaUnsupervisedInformationDisentanglement来源:https://doi.org/10.48550/arXiv.2211.10666https://conferencedemos.github.io/icassp23/主要贡献:1)定义了一个新的任务,称为timbre-controlledvideo-to-audi......
  • 题解:AT_abc372_e [ABC372E] K-th Largest Connected Components
    题意给出\(q\)个操作。将\(u\)和\(v\)连边。问\(u\)所在的连通块中编号第\(k\)大的点。思路连通块很容易想到并查集,求第\(k\)大可以用平衡树(虽然赛时没看到\(k\le10\)),合并时将信息从将小的连通块合并到大的连通块,这样可以减少时间复杂度。什么?你不会写平衡......
  • 鸿蒙跨端实践-长列表解决方案和性能优化
    这是我参加创作者计划的第一篇文章。 前言长列表是前端和客户端应用中最常见的业务场景,比如商品瀑布流等,有成千上万条数据,因此长列表的渲染性能在iOS,Android,Harmony,Web等各大平台都非常重要。HarmonyOS和iOS类似也提供了自己的解决方案。Roma(罗码)作为跨端平台,在此基础上......
  • 【理论篇】关于聚合根,领域事件的那点事---深入浅出理解DDD
    前言最近有空会跟同事讨论DDD架构的实践落地的情况,但真实情况是,实际中对于领域驱动设计中的实体,值对象,聚合根,领域事件这些战术类的实践落地,每个人理解依然因人而异,大概率是因为这些概念还是有一些抽象,同时有有别于传统的MVC架构开发。在此,通过小demo的方式跟大家分享一下我对DDD......