Iterator_fail-fast和Iterator_fail-safe~

news2024/11/16 21:34:02

初识fail-fast:

fail-fast 机制是java集合(Collection)中的一种错误机制当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件,它只是一种错误检测机制,只能被用来检测错误,因为JDK并不保证fail-fast机制一定会发生

fail-fast的作用:

当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了,那么线程A访问集合时,就会抛出
ConcurrentModificationException异常,产生fail-fast事件

举例:

准备实体类student:

public class Student {
    String name;
    public Student(String name){
        this.name=name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}

准备测试类:

import java.util.ArrayList;
public class MyArrayList {
    public static void main(String[] args) {
        ArrayList<Student> arrayList=new ArrayList<>();
        arrayList.add(new Student("A"));
        arrayList.add(new Student("B"));
        arrayList.add(new Student("C"));
        arrayList.add(new Student("D"));
        for(Student student:arrayList){
            System.out.println(student);
        }
        System.out.println(arrayList);
    }
}

第一步:设置断点

在这里插入图片描述

第二步:对测试类进行debug操作

在这里插入图片描述

第三步:查看当前输出结果

在这里插入图片描述

第三步:修改当前程序

在这里插入图片描述
在这里插入图片描述

第四步:使程序继续运行

在这里插入图片描述

fail-fast实现原理:

迭代器在遍历过程中是直接访问内部数据的,因此,内部的数据在遍历的过程中无法被修改,为了保证不被修改,迭代器内部维护了一个标记 “modCount ” ,当集合结构改变(添加删除或者修改),标记"modCount "会被修改,而迭代器每次的hasNext()和next()方法都会检查该"modCount "是否被改变,当检测到被修改时,抛出Concurrent Modification Exception

我们知道for循环的本质也是迭代,由此设置断点:

在这里插入图片描述

在这里插入图片描述

查看Iterator的源码,如下所示:

//modCount用来记录list修改的次数,每修改一次(添加/删除等操作),将modCount+1
protected transient int modCount = 0;


//返回list对应迭代器,实际上,是返回iterator对象
 public Iterator<E> iterator() {
        return new Itr();
    }


//Itr作为实现类实现Iterator接口
private class Itr implements Iterator<E> {
        int cursor;       
        int lastRet = -1; 
        //在迭代器初始化过程中会将modCount赋给迭代器的expectedModCount.目的是了在迭代过程中,通过next()方法会判断modCount跟expectedModCount是否相等,如果不相等就表示已经有其他线程修改了list,则会抛出ConcurrentModificationException异常,调动fail-fast机制
        int expectedModCount = modCount;

        
        Itr() {}

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

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

通过上面额源码我们学习到,若 “modCount 不等于 expectedModCount”,则抛出ConcurrentModificationException异常,产生fail-fast事件,那么什么时候modCount 不等于 expectedModCount?

测试方法如下:

第一步:添加断点—>debug测试类

在这里插入图片描述

第二步:运行程序

在这里插入图片描述

第三步:debugger处理:

在这里插入图片描述
在这里插入图片描述

添加成功后该值变为5:

在这里插入图片描述

第四步:在调用checkForComodification方法时,添加断点

在这里插入图片描述

继续运行程序:

在这里插入图片描述

我们再去查看modCount和expectedModCount的大小关系如下:

在这里插入图片描述

fail-safe:

发现遍历的同时其他人来修改,应当有应对策略,例如:牺牲一致性来让整个遍历运行完成

fail-safe的作用:

采用fail-safe机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历

举例:

实体类不变还是上述fail-fast中的Student类

测试类代码如下:

import java.util.concurrent.CopyOnWriteArrayList;
public class MyArrayList {
    public static void main(String[] args) {
        CopyOnWriteArrayList<Student> copyOnWriteArrayList=new CopyOnWriteArrayList<>();
        copyOnWriteArrayList.add(new Student("A"));
        copyOnWriteArrayList.add(new Student("B"));
        copyOnWriteArrayList.add(new Student("C"));
        copyOnWriteArrayList.add(new Student("D"));
        for(Student student:copyOnWriteArrayList){
            System.out.println(student);
        }
        System.out.println(copyOnWriteArrayList);
    }
}

重复和上述fail-fast相同的步骤!

添加条件断点:

在这里插入图片描述

debug测试类:

在这里插入图片描述

继续运行程序:查看输出结果

在这里插入图片描述

虽然这种方法并没有报错,且添加的元素都能够被运行,但是我们会发现在遍历的过程中,并没有输出元素E,而在最后打印列表元素时,才有元素E的输出,其实这种情况就称为通过牺牲一致性来保证整个列表的遍历

fail-safe实现原理:

fail-safe任何对集合结构的修改都会在一个复制的集合上进行修改,因此不会抛出ConcurrentModificationException

步骤与fail-fast相同,这里我们只说不同的地方!

在这里插入图片描述

查看COWIterator源码:

在这里插入图片描述

当我们添加元素之后查看array数组中的元素,发现目前存在5个元素:

在这里插入图片描述

但是迭代器中的元素依然为4个:

在这里插入图片描述

这说明遍历时的数组和迭代的数组不是同一个!

查看add源码,如下所示:

在这里插入图片描述

点击setArray源码,如下所示:

在这里插入图片描述

最终会将元素添加完成后的数组输出,因此遍历出的数组包含新添加的元素

fai-fast与fail-safe小结:

ArrayList是fail-fast的典型代表,遍历的同时不能修改,否则会抛出异常

CopyOnWriteArrayList是fail-safe的典型代表,遍历的同时可以修改,原理是读写分离

fail-safe机制的缺点:

需要复制集合,产生大量的无效对象,开销大

无法保证读取的数据是目前原始数据结构中的数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/184573.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝桥杯2022Python组

蓝桥杯2022Python组 1.排列字母 用一个sorted就好了&#xff0c;没啥好说的 s WHERETHEREISAWILLTHEREISAWAY s sorted(s) # 变成列表形式了 print(.join(s))2.寻找整数 这题我刚开始以为答案只能是11和17的倍数&#xff0c;就在他们的倍数里面找&#xff0c;发现不对&…

STL——STL简介、STL六大组件

一、STL是什么 STL(standard template library)&#xff1a; C标准模板库&#xff0c;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;还是一个包罗数据结构与算法的软件框架。 通俗来讲&#xff1a; STL就是将常见的数据结构&#xff08;顺序表、…

Superset权限管理

文章目录1.Superset角色1&#xff09;Admin2&#xff09;Alpha3&#xff09;Gamma4&#xff09;Sql_lab5&#xff09;Public2.实操自定义授权1&#xff09;权限集2&#xff09;实操1.Superset角色 Superset的默认角色有&#xff1a;Admin、Alpha、Gamma、sql_lab、Public 1&a…

【信息资源建设】

考试分为单选、判断改错、名词解释、简答、综合论述 1.1 如果按价值观念划分&#xff0c;则可将信息分为有用信息和无用信息 信息的特性&#xff1a;普遍性、客观性、时效性、传递性、共享性、变换性、转化性、可伪性。 1.1.2 &#xff08;必考&#xff09;OECD的知识分类…

【docker概念和实践 4】(4) 本地镜像提交到本地仓库

一、说明 registry是一个镜像&#xff0c;该镜像专门生成镜像仓库的容器&#xff0c;registry是基于http协议&#xff0c;那就是说&#xff0c;在单机、局域网、或者互联网上都可以建立registry数据仓库&#xff0c;存放自己构建的镜像。本篇专门介绍如何在本地单机上建立容器仓…

Python中的集合(set and frozenset)语法汇总

集合的基本语法知识目前有两种集合类型&#xff1a;set和frozenset。可变集合&#xff1a;set()set类型是可变的&#xff0c; 其内容可以使用 add() 和 remove() 这样的方法来改变&#xff0c;因为是可变的&#xff0c;所以没有哈希值&#xff0c;且不能被用作字典的键或其它集…

java线上项目排查,Arthas简单上手

Arthas 是Alibaba开源的Java诊断工具。参考&#xff1a;Arthas 用户文档 — Arthas 3.5.4 文档 当你遇到以下类似问题而束手无策时&#xff0c;Arthas可以帮助你解决&#xff1a; 这个类从哪个 jar 包加载的&#xff1f;为什么会报各种类相关的 Exception&#xff1f;我改的代…

一起Talk Android吧(第四百七十九回:集合类视图动画)

文章目录使用方法属性介绍示例代码各位看官们大家好&#xff0c;上一回中咱们说的例子是"旋转类视图动画",这一回中咱们说的例子是"集合类视图动画"。闲话休提&#xff0c;言归正转&#xff0c;让我们一起Talk Android吧&#xff01; 使用方法 集合类动画…

web测试2:嵌入式移植boa

读此篇之前&#xff0c;先读前一篇 1.在源码编译的时候&#xff0c;指定交叉编译工具链 lkmaoubuntu:~$ arm-linux-gnueabi-gcc --version arm-linux-gnueabi-gcc (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 Copyright (C) 2015 Free Software Foundation, Inc.…

C++工程的CMakeLists.txt文件编写

最简单的demo工程如下&#xff1a; #include <iostream> #include <string> int main(int argc,char** argv) {std::cout << "hello world" << std::endl;return 0; } 文件结构如下&#xff0c;其中include可用来自定义接口功能类。 CMake…

IMX Linux 用户手册 --- 1

IMX Linux 用户手册 — 1 第一章 概述 本文档介绍了i.MX LinuxOS BSP (BSP代表Board Support Package)在i.MX平台上的构建和安装方法。它还涵盖了特殊的i.MX功能和如何使用它们。 本文档还提供了运行i.MX平台的步骤&#xff0c;包括单板拨码开关设置、U-Boot引导加载程序的配置…

IP地址是什么

我们知道&#xff0c;网络通讯的本质就是收发数据包。如果说收发数据包就跟收发快递一样。那IP地址就类似于快递上填的收件地址和发件地址一样&#xff0c;有了它&#xff0c;路由器就可以开始充当快递员的角色&#xff0c;在这个纷繁复杂的网络世界里找到该由谁来接收这个数据…

linux上git三板斧的使用

前言 现在在我们的生活当中&#xff0c;用我们程序员的一句玩笑话&#xff0c;来说就是“全球最大的同性交友网站就是githup”。 那么它具有什们功能呢&#xff0c;能让人这么吹捧&#xff0c;用通俗易懂的话来说就是&#xff0c;储存和管理代码&#xff0c;它会记录我们修改甚…

java知识总结(一)

ArrayList和LinkedList的区别1. ArrayList的实现是基于数组,LinkedList的实现是基于双向链表。2. 对于随机访问ArrayList要优于LinkedList,ArrayList可以根据下标以O(1)时间复杂度对元素进行随机访问,而LinkedList的每一个元素都依靠地址指针和它后一个元素连接在一起,查找某个…

【开发工具 - 安装手册】BeyondCompare4 下载与安装+免费使用

1. 官网 Download Beyond Compare Free Trial 2. 下载 阿里云盘 &#xff08;不限速 - 推荐&#xff09;官网下载3. 安装&#xff08;无脑下一步&#xff09; 4.三种方法长期免费使用 方法一 修改初始化文件 C:\Users\Administrator\AppData\Roaming\BCompare\BCompare.ini…

【奇妙的数据结构世界】用图像和代码对队列的使用进行透彻学习 | C++

第十一章 队列 目录 第十一章 队列 ●前言 ●一、队列是什么&#xff1f; 1.简要介绍 2.具体情况 ●二、队列操作的关键代码段 1.类型定义 2.顺序队列的常用操作 3.链式队列的常用操作 ●总结 前言 简单来说&#xff0c;数据结构是一种辅助程序设计并且进行优化的方法论&…

介绍一款2023年新出的mysql管理工具: FlyBird Database Manager

FlyBird Database Manager 介绍 FlyBird Database Manager 是一款mysql 界面化管理工具&#xff0c; 使用go语言编写&#xff0c;天然支持Windows, MacOS, Linux等主流平台。 提供无需安装的命令行版本&#xff0c; 命令行中启动服务&#xff0c;以html支持UI界面,在浏览器中…

[Linux]进程控制

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【LINUX】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文…

1607_PC汇编语言_汇编语言简介

全部学习汇总&#xff1a; GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 刚刚看了一个小章节&#xff0c;感觉是对8086的汇编做了一个简单的介绍。当然&#xff0c;这里面也有各种机器汇编通用的属性。 1. 等价符号关联的两个表达其实是等…

在线教育-谷粒学院学习笔记(十)

文章目录1 介绍2 登录业务流程3 JWT令牌4 阿里云短信服务5 登录功能6 注册功能7 根据token获取用户信息8 整合首页登录和注册1 介绍 登录实现流程 注册接口 整合JWT整合阿里云短信服务 登录接口 注册、登录的前端实现 2 登录业务流程 单一服务器模式 使用session对象实现 …