迭代器生成器可迭代对象_使用迭代器时如何避免ConcurrentModificationException

迭代器生成器可迭代对象

Java Collection类是快速失败的,这意味着如果在使用迭代器遍历某个线程的同时更改了Collection,则iterator.next()将抛出ConcurrentModificationException 。

在多线程以及单线程环境中都可能出现这种情况。

让我们通过以下示例探索这种情况:

import java.util.*;public class IteratorExample {public static void main(String args[]){List<String> myList = new ArrayList<String>();myList.add("1");myList.add("2");myList.add("3");myList.add("4");myList.add("5");Iterator<String> it = myList.iterator();while(it.hasNext()){String value = it.next();System.out.println("List Value:"+value);if(value.equals("3")) myList.remove(value);}Map<String,String> myMap = new HashMap<String,String>();myMap.put("1", "1");myMap.put("2", "2");myMap.put("3", "3");Iterator<String> it1 = myMap.keySet().iterator();while(it1.hasNext()){String key = it1.next();System.out.println("Map Value:"+myMap.get(key));if(key.equals("2")){myMap.put("1","4");//myMap.put("4", "4");}}}
}

输出为:

List Value:1
List Value:2
List Value:3
Exception in thread "main" java.util.ConcurrentModificationExceptionat java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)at java.util.AbstractList$Itr.next(AbstractList.java:343)at com.journaldev.java.IteratorExample.main(IteratorExample.java:27)

从输出堆栈跟踪中可以明显看出,当我们调用迭代器next()函数时,异常即将到来。 如果您想知道Iterator如何检查修改,则它的实现存在于AbstractList类中,其中定义了一个int变量modCount,该变量提供了更改列表大小的次数。 该值在每个next()调用中使用,以检查功能checkForComodification()中是否有任何修改。

现在,注释列表部分并再次运行该程序。

输出将是:

Map Value:3
Map Value:2
Map Value:4

由于我们正在更新myMap中的现有键值,因此其大小没有更改,并且没有收到ConcurrentModificationException。 请注意,输出结果可能在您的系统中有所不同,因为HashMap键集的排序不像list那样。 如果您将在HashMap中添加新键值的语句取消注释,则将导致ConcurrentModificationException。

要在多线程环境中避免ConcurrentModificationException:

1.您可以将列表转换为数组,然后在数组上进行迭代。 这种方法适用于中小型列表,但是如果列表很大,则对性能的影响很大。

2.您可以通过将列表放在同步块中来在锁定时锁定列表。 不建议使用此方法,因为它将停止多线程的好处。

3.如果使用的是JDK1.5或更高版本,则可以使用ConcurrentHashMap和CopyOnWriteArrayList类。 这是推荐的方法。

要在单线程环境中避免ConcurrentModificationException:

您可以使用迭代器remove()函数从基础集合对象中删除该对象。 但是在这种情况下,您可以从列表中删除同一对象,而不能删除任何其他对象。

让我们使用并发集合类运行示例:

package com.journaldev.java;import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;public class ThreadSafeIteratorExample {public static void main(String[] args) {List<String> myList = new CopyOnWriteArrayList<String>();myList.add("1");myList.add("2");myList.add("3");myList.add("4");myList.add("5");Iterator<String> it = myList.iterator();while(it.hasNext()){String value = it.next();System.out.println("List Value:"+value);if(value.equals("3")){myList.remove("4");myList.add("6");myList.add("7");}}System.out.println("List Size:"+myList.size());Map<String,String> myMap = new ConcurrentHashMap<String,String>();myMap.put("1", "1");myMap.put("2", "2");myMap.put("3", "3");Iterator<String> it1 = myMap.keySet().iterator();while(it1.hasNext()){String key = it1.next();System.out.println("Map Value:"+myMap.get(key));if(key.equals("1")){myMap.remove("3");myMap.put("4", "4");myMap.put("5", "5");}}System.out.println("Map Size:"+myMap.size());}}

输出为:

List Value:1
List Value:2
List Value:3
List Value:4
List Value:5
List Size:6
Map Value:1
Map Value:null
Map Value:4
Map Value:2
Map Size:4

从上面的示例可以清楚地看出:

1.可以修改Concurrent Collection类,避免ConcurrentModificationException 。

2.对于CopyOnWriteArrayList ,迭代器不适应列表中的更改,并且可以处理原始列表。

3.对于ConcurrentHashMap ,行为并不总是相同的。

条件:

if(key.equals("1")){myMap.remove("3");

输出为:

Map Value:1
Map Value:null
Map Value:4
Map Value:2
Map Size:4

它正在使用添加了键“ 4”的新对象。 但不是下一个键为“ 5”的对象。

现在,如果我将条件更改为

if(key.equals("3")){myMap.remove("2");

输出为:

Map Value:1
Map Value:3
Map Value:null
Map Size:4

在这种情况下,它不考虑新添加的对象。

因此,如果您使用的是ConcurrentHashMap,请避免添加新对象,因为可以根据键集对其进行处理。 请注意,同一程序可以在您的系统中打印不同的值,因为HashMap键集没有任何顺序。

额外的浇头:

for(int i = 0; i<myList.size(); i++){System.out.println(myList.get(i));if(myList.get(i).equals("3")){myList.remove(i);i--;myList.add("6");}
}

如果您在单线程环境中工作,并且希望您的代码处理列表中额外添加的对象,则可以使用以下代码并避免使用迭代器。

请注意,由于要删除同一对象,所以要减少计数器,如果必须删除下一个或更远的对象,则不需要减少计数器。

自己尝试。

参考:在JournalDev上 使用 JCG合作伙伴提供的迭代器时如何避免ConcurrentModificationException

    相关文章:

    • Java最佳实践– Vector vs ArrayList vs HashSet
    • Java最佳实践–队列之战和链接的ConcurrentHashMap
    • Java Fork / Join进行并行编程
    • ConcurrentLinkedHashMap v 1.0.1发布
    相关片段:
    • 阻塞队列示例以执行命令
    • 信号量示例限制URL连接
    • 执行命令的同步队列示例
    • 更一般的等待/通知机制的CountDownLatch示例

    翻译自: https://www.javacodegeeks.com/2011/05/avoid-concurrentmodificationexception.html

    迭代器生成器可迭代对象

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

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

    相关文章

    Console命令详解,让调试js代码变得更简单

    刚刚在浏览关于js方面的博客时发现这个方法挺好玩的&#xff0c;自己爽了一把。 1 <script> 2 console.time(/X(.)X/ test); 3 "XX".match(/X(.)X/); 4 console.timeEnd(/X(.)X/ test); 5 </script> 然后恶补了一下关于Firebug控制台的知识。熟练地使用…

    mysql as tmp,启动mysql时显示:/tmp/mysql.sock 不存在的解决办法

    启动mysql时显示&#xff1a;/tmp/mysql.sock 不存在的解决方法启动mysql时显示&#xff1a;/tmp/mysql.sock 不存在的解决方法启动mysql时报错的解决(mysql 5.0.45 redhat as43)启动mysql时报错的解决(mysql 5.0.45 redhat as 43)作者: lawzjf(http://lawzjf.itpub.net)发表于…

    PHP求体重成绩函数,PHP数组

    数组提出一个问题&#xff1a;一个养鸡场有6只鸡&#xff0c;他们的体重分别为3kg&#xff0c;5kg&#xff0c;1k个&#xff0c;3.4kg&#xff0c;2kg&#xff0c;6.kg请问这六只鸡的总体重是多少平均体重是多少请你用现在掌握的技术编一个程序现在我们使用现有的技术来解决问题…

    Sublime Text 3插件之Emmet:HTML/CSS代码快速编写神器

    一、快速编写HTML代码 1. 初始化 HTML文档需要包含一些固定的标签&#xff0c;比如<html>、<head>、<body>等&#xff0c;现在你只需要1秒钟就可以输入这些标签。比如输入“!”或“html:5”&#xff0c;然后按Tab键&#xff1a; html:5 或!&#xff1a;用于…

    批处理停止php服务,通过批处理启动和停止MSSQL+IIS

    电脑安装了不少的开发工具环境&#xff0c;如MSSQL2005(2000)IIS\MySQLApache等等&#xff0c;开机和娱乐时为了加快速度&#xff0c;都得把这些占用内存的开发工具系统服务停止&#xff0c;每项手工操作明显麻烦&#xff0c;用批处理就简单多了... 点一下启动&#xff0c;再点…

    k8s secret使用_Java Secret:使用枚举构建状态机

    k8s secret使用总览 Java中的枚举比许多其他语言更强大&#xff0c;可以导致令人惊讶的用途。 在本文中&#xff0c;我概述了Java 枚举的一些单独功能&#xff0c;并将它们放在一起形成一个状态机。 单例和实用程序类的枚举 您可以非常简单地将枚举用作Singleton或Utility。…

    mydumper备份原理和使用方法

    mydumper介绍 MySQL自身的mysqldump工具支持单线程工作&#xff0c;依次一个个导出多个表&#xff0c;没有一个并行的机&#xff0c;这就使得它无法迅速的备份数据。 mydumper作为一个实用工具&#xff0c;能够良好支持多线程工作&#xff0c;可以并行的多线程的从表中读入数据…

    大津阈值分割matlab实验,OTSU(大津法)分割源程序(MATLAB版)

    接下来介绍OTSU方法的原理&#xff1a;***************************************************************************************************************************************************************OTSU法对于具有双峰性质的灰度图像或是彩色图像的某一通道的分割效…

    BZOJ-1798 维护序列

    线段树。支持区间加、区间乘、区间查询和。 标记下移还有取模要注意。 var n,p,q,i,s,t:longint; a:int64; num,n1,n2,n3:array[0..500000] of int64; procedure build(o,l,r:longint); var m,i:longint; begin m:(lr) div 2; if lr then begin n1[o]:num[l];…

    matlab pca可视化,利用Matlab实现PCA demo展示

    input_data rand(1000,3);%随机生成1000个样本&#xff0c;每个样本有x,y,z三个属性 figure(1);%控制画图的窗口为1hold off;%使当前轴和图形不再具备被刷新的性质&#xff0c;关闭在此基础上再画图plot3(input_data(:,1), input_data(:,2), input_data(:,3), ‘ro‘);%% Func…

    matlab短均线滞后项,均线理论的滞后性问题

    对移动平均线有一定了解的人都会发现移动平均线理论存在一个缺点&#xff0c;那就是移动平均线的信号具有一定的滞后性&#xff0c;这是制约移动平均线运用的最大因素。介绍了均线的计算方法.从它的计算方法中也能看出目前均线的数值要受到前一阶段股价的影响&#xff0c;而且均…

    IOS侧滑框架合集

    侧滑框架 https://github.com/gresrun/GHSidebarNav https://github.com/ipup/PPRevealSideViewController https://github.com/gotosleep/JASidePanels https://github.com/jamztang/JTRevealSidebarDemo https://github.com/ECSlidingViewController/ECSlidingViewController…

    python捕获摄像头帧_Xuggler教程:帧捕获和视频创建

    python捕获摄像头帧注意&#xff1a;这是我们的“ Xuggler开发教程 ”系列的一部分。 到目前为止&#xff0c;在我们的Xuggler教程系列中&#xff0c;我们已经对视频处理的Xuggler进行了介绍&#xff0c;并讨论了转码和媒体修改 。 在本教程中&#xff0c;我们将看到如何解码视…

    【python核心编程】第六章 序列

    1、操作符 &#xff08;1&#xff09;成员关系操作符&#xff1a;in 、not in >>> string abcdefg>>> a in stringTrue>>> h in stringFalse>>> h not in stringTrue *补充知识*&#xff1a;string模块 >>> import string>>…

    java物业管理系统设计,JAVA物业管理系统设计与实现(论文+源代码)

    【实例简介】JAVA物业管理系统设计与实现(论文源代码)【实例截图】【核心代码】JAVA物业管理系统设计与实现(论文源代码)└── JAVA物业管理系统设计与实现(论文源代码)├── JAVA物业管理系统设计与实现(论文源代码)│ ├── JAVA物业管理系统│ │ ├── JWS│ │…

    MyEclipse 编写 ExtJS 卡死问题解决方法

    MyEclipse 8.6 在 jsp 中编写 ExtJS时&#xff0c;会出现卡死现象&#xff0c;让人甚是头疼。网上找了很多方法&#xff0c;折腾半天&#xff0c;还是不管用。 什么MyEclipse 优化&#xff0c;Validation 取消&#xff0c;MyEclipse 在 JSP 中打 "点" 时&#xff0…

    matlab试用版的user id,免费试用MATLAB

    请选择其一AlabamaAlaska美属萨摩亚APO/FPO AAAPO/FPO AEAPO/FPO APArizonaArkansasCaliforniaCaroline IslandsColoradoConnecticutDelawareDistrict of ColumbiaFlorida格鲁吉亚关岛HawaiiIdahoIllinoisIndianaIowaKansasKentuckyLouisianaMaineMariana Islands马绍尔群岛Mar…

    java的aqs是什么,AQS在Java中的应用

    上篇文章我们详细分析了AQS的底层实现原理,这节就来探索jdk中使用AQS实现的工具类ReentrantLock一, 是什么?怎么用?是什么?是一个独占锁,也就是在并发环境下同一时刻只能有一个线程获得资源,也是一个可重入锁.可重入锁: 一个线程已经获取到了该资源,下次再次获取资源时不会出…

    jasper 获取当前日期_入侵Jasper以获取JSP页面的对象模型

    jasper 获取当前日期为了对我的JSP执行一些检查和统计分析&#xff0c;我需要一个包含在其中的元素的类似于DOM的层次模型。 但是&#xff0c;解析JSP页面并不是一件容易的事&#xff0c;最好留给它一个出色的工具-Tomcat&#xff0c;Jetty&#xff0c;GlassFish以及其他所有工…

    php怎么把字符转成大写,php怎么把字符串转换为大写

    php把字符串转换为大写的方法&#xff1a;可以利用内置函数strtoupper()来进行转换。strtoupper()函数可以把指定的字符串转换为大写&#xff0c;并返回被转换为大写的字符串。使用函数&#xff1a;(学习视频推荐&#xff1a;php视频教程)strtoupper() 函数把字符串转换为大写&…