for循环中list触发fast-fail或不触发的原理和方法

Iterable和Iterator

在这里插入图片描述
Iterator接口位于的位置是java.util.Iterator,它主要有两个抽象方法供子类实现。hasNext()用来判断还有没有数据可供访问,next()用来访问下一个数据。

集合Collection不是直接去实现Iterator接口,而是去实现Iterable接口。在这里插入图片描述
用这个Iterable接口的iterator()方法返回当前集合迭代器。
集合Collection体系的集合都得按照使用iterator()的方式返回可供遍历的迭代器iterator
在这里插入图片描述
集合使用Iterable接口的iterator()方法返回迭代器Iterator有很多好处。
在这里插入图片描述
比如有两个线程都需要使用迭代器进行遍历集合的操作,如果通过直接实现Iterator接口来拿迭代器。首先两者拿的是同一个迭代器,并且两者不同步,一个都遍历结束了,另一个都还没开始就无法遍历集合了,但是他本来循环从头开始遍历集合的所有数据的。

如果使用Iterable接口的iterator()方法返回迭代器Iterator,那两者获得的就是不同迭代器了,就互不影响,自己可以按照自己的进度遍历集合就行。
在这里插入图片描述


for-each就是迭代器的语法糖,增强版的 for 循环(也叫 “for-each” 循环)在 Java 中是一个特性,它允许你遍历任何实现了 Iterable 接口的集合或者数组。
要使用增强型 for 循环(也称为 for-each 循环)遍历一个集合,集合的类需要实现 java.lang.Iterable 接口。Iterable 接口定义了一个方法 iterator(),它返回一个 Iterator 对象,用于遍历集合的元素。

import java.util.Iterator;
import java.util.NoSuchElementException;

// Iterable位于java.lang包下,不用显式import
public class MyCollection<T> implements Iterable<T> {
    private T[] elements;
    private int size;

    @SuppressWarnings("unchecked")
    public MyCollection(int capacity) {
        elements = (T[]) new Object[capacity];
        size = 0;
    }

    public void add(T element) {
        if (size < elements.length) {
            elements[size++] = element;
        } else {
            throw new IllegalStateException("Collection is full");
        }
    }
	
	// 当一个类要实现 Iterable 接口,它必须提供一个 iterator() 方法,该方法返回一个 Iterator 对象。
    @Override
    public Iterator<T> iterator() {
        return new MyIterator();
    }

    private class MyIterator implements Iterator<T> {
        private int currentIndex = 0;

        @Override
        public boolean hasNext() {
            return currentIndex < size;
        }

        @Override
        public T next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            return elements[currentIndex++];
        }
    }
}
MyCollection<String> collection = new MyCollection<>(10);
        collection.add("a");
        collection.add("b");
        collection.add("c");

        // 使用增强型 for 循环
        for (String element : collection) {
            System.out.println(element);
        }

        // 和增强for循环等价的显式迭代器循环
        // 当一个类实现了 Iterable 接口,它必须提供一个 iterator() 方法,该方法返回一个 Iterator 对象。
        // 这个 Iterator 对象实现了 hasNext() 和 next() 方法,用于遍历集合中的元素。
        // 下面的 iterator 是通过集合类实现的 Iterable 接口的 iterator() 方法获得的
        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println(element);

快速失败机制的工作原理

fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件
Java中的集合类(如ArrayList、LinkedList、HashMap等)使用快速失败机制来检测在迭代过程中对集合的结构性修改。
工作原理如下:

  1. modCount:每个集合类都有一个modCount字段,用于记录集合结构性修改的次数。结构性修改是指添加或删除元素,改变集合的大小。
  2. 迭代器的expectedModCount:当创建迭代器时,迭代器会保存当前集合的modCount值到一个名为expectedModCount的字段中。
  3. 一致性检查:在每次调用迭代器的next()hasNext()方法时,迭代器首先会检查modCount是否与expectedModCount相同。如果不相同,说明集合在迭代过程中的结构被修改过,迭代器会抛出ConcurrentModificationException

总的来说:只要是涉及了改变ArrayList元素的个数的方法都会导致modCount的改变。当多线程环境下,由于expectedModCount与modCount的改变不同步,导致两者之间不等,从而产生fast-fail。

在这里插入图片描述
这里的抛出异常,停止执行就是fail-fast,就是当自己遇到无法处理的情况时的处理方式。

下面是ConcurrentModificationException异常的例子:

List<String> list = new ArrayList<>();
list.add("a");
Iterator<String> iterator = list.iterator();  // expectedModCount = modCount = 0
list.add("b");  // modCount = 1
iterator.next(); // expectedModCount != modCount, 抛出ConcurrentModificationException异常

for-each循环对集合进行增删也可能抛出异常,因为for-each在反编译下可以发现就是迭代器的语法糖,所以涉及到对迭代器的使用。

		List<String> collection = new ArrayList<>();
		collection.add("a");
		collection.add("b");
		// 使用增强型 for 循环
        for (String element : collection) {
            System.out.println(element);
        }

        // 和增强for循环等价的显式迭代器循环
        // 当一个类实现了 Iterable 接口,它必须提供一个 iterator() 方法,该方法返回一个 Iterator 对象。
        // 这个 Iterator 对象实现了 hasNext() 和 next() 方法,用于遍历集合中的元素。
        // 下面的 iterator 是通过集合类实现的 Iterable 接口的 iterator() 方法获得的
        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            if ("a".equals(element)) {
            	collection.remove(element);
            }
         }

想要在循环时进行增删操作,也就是进行这类对集合结构性有影响的操作,就要保证数据隔离性,下面是三种数据隔离性的处理方式,本质都是复制东西,只是复制的东西有所不同。
在这里插入图片描述
写入时复制(copy-on-write, 简称COW)。
在这里插入图片描述

在这里插入图片描述
GC 代表 “Garbage Collection”(垃圾回收)。COW读操作时并没有加锁,这是为了提高读操作的性能,但是有缺点,比如读数据的时候可能读不到最新的数据。例如,线程1往集合里面add数据才增加了一半,线程2这时候就去读数据,那读到的就还是老数据。

在这里插入图片描述
这样的话就只有增删才需要开辟一个新数组,其他情况都是使用原数组引用来读取原数组。

// 可以像使用普通的 ArrayList 一样使用 CopyOnWriteArrayList(写入时复制),并且可以通过 List 接口来引用它
        List<String> cowList = new CopyOnWriteArrayList<>();
        cowList.add("a");
        cowList.add("b");
        cowList.add("c");

        Iterator<String> iterator = cowList.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        cowList.remove("b");
        Iterator<String> iterator2 = cowList.iterator();
        while (iterator2.hasNext()) {
            System.out.println(iterator2.next());
        }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Pycharm设置远程解释器(本地代码+远程服务器环境)

Pycharm设置远程解释器(本地代码+服务器环境) Pycharm设置远程开发环境: 1.点击IDE左上角“文件”-》点击其中的设置 2:点击项目->点击添加解释器 3: 4根据提示填入远程服务器的IP地址,端口,和用户名: 5:连接上后选择现有环境: 6:选择刚才建立好的conda环境…

ubnutu20.04-vscode安装leetcode插件流程

1.在vscode插件商城选择安装leetcode 2.安装node.js 官网下载一个版本安装流程&#xff1a; ①tar -xvf node-v14.18.0-linux-x64.tar.xz ①sudo ln -s /app/software/nodejs/bin/npm /usr/local/bin/ ②ln -s /app/software/nodejs/bin/node /usr/local/bin/ 查看版本&…

G1 垃圾收集器

从 JDK1.9 开始默认 G1&#xff0c;应用在多处理器和大容量内存环境中。 基础概念 Region G1 给整一块Heap内存区域均匀等分了N个 Region&#xff0c;N 默认情况下是 2048。 Region的大小只能是1M、2M、4M、8M、16M或32M (1-32M,并且为2的指数)&#xff0c;比如-Xmx16g -Xms…

【Unity 角色控制器组件】

【Unity 角色控制器组件】 Character Controller&#xff1a; Unity 内置的一个组件&#xff0c;用于提供高级的物理控制&#xff0c;允许开发者控制角色的移动、跳跃和碰撞。 csharp csharp // 假设你已经有了一个带有Character Controller组件的游戏对象// 获取Character Co…

第十四章 路由器 OSPF 动态路由配置

实验目的 掌握 OSPF 协议的配置方法&#xff1a; 掌握查看通过动态路由协议 OSPF 学习产生的路由&#xff1b; 熟悉广域网线缆的链接方式&#xff1b; 实验背景 假设校园网通过一台三层交换机连到校园网出口路由器上&#xff0c; 路由器再和校园外的另一台路由器连接。…

Java高级重点知识点-19-Lambda

文章目录 Lambda表达式函数式编程思想Lambda表达式写法代码讲解 Lambda表达式 函数式编程思想 强调做什么&#xff0c;而不是以什么形式做。 以函数式接口Runnable为例讲解&#xff1a; public class LambdaDemo {public static void main(String[] args) {Runnable runnab…

relation-graph——数据组装+鼠标移入后的详情(自定义插槽的用法)——js技能提升

最近在写后台管理系统的时候&#xff0c;遇到一个需求&#xff0c;就是给我一些节点&#xff0c;让我渲染到页面上&#xff0c;效果图如下&#xff1a; 之前写过一篇文章关于relation-graph关系图组件http://t.csdnimg.cn/7BGYm的用法 还有一篇关于relation-graph——实现右击…

Python 编程快速上手——让繁琐工作自动化(第2版)读书笔记01 Python基础快速过关

Python 编程快速上手——让繁琐工作自动化&#xff08;第2版&#xff09;读书笔记01 Python基础快速过关 1 python基础概念 Python提供了高效的高级数据结构&#xff0c;还能简单有效地面向对象编程。 python运算符顺序 **——%——//——/——*——-——python中常见的数据…

【085】基于SpringBoot实现的网上音乐商城平台

系统介绍 视频演示 点击查看演示视频 基于SpringBoot实现的网上音乐商城平台分为管理员、用户两个角色&#xff0c;系统实现了用户注册和登陆、用户信息管理、用户加购、下单商品、购物车管理、订单管理、音乐分类、音乐商品管理、退出系统等功能 技术选型 开发工具&#…

大数据基础知识【大数据导论】

各位大佬好 &#xff0c;这里是阿川的博客&#xff0c;祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 大数据基础知识前 必看 【大数据导论】—大数据序言…

旅游管理系统16021

摘 要 本文旨在设计和实现一个基于Spring Boot框架的旅游管理系统。该系统通过利用Spring Boot的快速开发特性和丰富的生态系统&#xff0c;提供了一个高效、可靠和灵活的解决方案。系统将实现旅游景点信息的管理、线路规划、跟团游玩、旅游攻略、酒店信息管理、订单管理和用户…

【C语言】inline 关键字

在C语言中&#xff0c;inline关键字用于建议编译器对函数进行内联展开&#xff0c;而不是像普通函数一样调用。内联函数的目的是减少函数调用的开销&#xff0c;特别是对于简单的、频繁调用的函数。 内联函数的定义和使用 定义内联函数 要定义一个内联函数&#xff0c;需要在…

PyTorch之nn.Module、nn.Sequential、nn.ModuleList使用详解

文章目录 1. nn.Module1.1 基本使用1.2 常用函数1.2.1 核心函数1.2.2 查看函数1.2.3 设置函数1.2.4 注册函数1.2.5 转换函数1.2.6 加载函数 2. nn.Sequential()2.1 基本定义2.2 Sequential类不同的实现2.3 nn.Sequential()的本质作用 3. nn.ModuleList参考资料 本篇文章主要介绍…

应用密码学—(扩展)欧几里得、DES、RSA、SHA-1算法

1. 欧几里得算法 1.1 分析算法的实现原理 欧几里德&#xff08;Euclid&#xff09;算法&#xff0c;也既常说的“辗转相除法”&#xff0c;公式为gcd(m, n) { return gcd(n, m%n); }&#xff0c;对于任意两个正整数m、n&#xff0c;每次求的一个数字r m % n&#xff0c;然后把…

sideloadly 苹果自签和sidestore手机续签ipa记录

sideloadly 地址&#xff1a;https://sideloadly.io/#download 直接安装对应系统软件&#xff0c;然后吧ipa 拖到里面续签&#xff0c;缺点每7天需要电脑续签 如果续签保留数据需要对应的位置开启 enable file sharing 勾选 和 bundle id 修改 注意的地方需要电脑和手机appi…

无人机热成像分析图谱原理

一、热成像原理 热成像&#xff0c;也称为红外热成像或红外成像&#xff0c;是一种利用红外辐射&#xff08;通常指的是热辐射&#xff09;来获取物体表面温度分布信息的成像技术。在无人机上集成热成像传感器&#xff0c;可以远程捕获并分析目标物体的热特征&#xff0c;不受…

卸载node,下载nvm,下载node过程步骤及错误记录

网上有很多步骤&#xff0c;先跟着网上的步骤来&#xff1a; 卸载node和下载nvm步骤&#xff1a; window下安装并使用nvm&#xff08;含卸载node、卸载nvm、全局安装npm&#xff09;-CSDN博客 使用NVM下载和安装NodeJS教程-CSDN博客 出现的问题&#xff1a; 1.nvm配置sett…

ENVI5.6使用笔记

目录 1. ENVI安装扩展2. ENVI绘制高光谱3D数据立体图3. 对本次工作存档&#xff0c;下次打开软件可直接续档 1. ENVI安装扩展 从ENVI App Store下载商店envi_app_store.zip&#xff0c;解压得到ENVI_App_Store.sav&#xff0c;将其复制到ENVI的扩展文件夹下&#xff08;例如E:…

中国桥梁空间分布数据

2020年中国桥梁空间分布数据&#xff0c;共包含102000余条数据。 数据属性表包括&#xff1a;地级市名、区县名、桥梁名称和经纬度。有shp和EXCEl两种格式数据。目前暂没有广西、广东和台湾三个省份数据。

【js】数组元素拼接、数组元素类型转换

一、数组元素拼接 二、数组元素类型转换 1、字符串数组 转换成 数字型数组 [1, 2, 3].map(Number) // [1,2,3] 2、数字型数组 转换成 字符串数组 [1, 2, 3].map(String) // [1, 2, 3]
最新文章