java 并发操作list集合导致java.util.ConcurrentModificationException

需求:我有一个集合,如下,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现

代码如下:

public class Test {
		public static void main(String[] args) {
			List<String> list = new ArrayList<String>();

			list.add("java");
			list.add("world");
			list.add("android");

			Iterator<String> iterator = list.iterator();
			while(iterator.hasNext()){
				String content = iterator.next();
				if("world".equals(content)){
					list.add("hello");
				}
			}
			System.out.println(list);
		}
}

运行报错信息:

首先我们打开jdk文档查看下这个异常,因为java是面向对象语言,异常也封装成了对象,

ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

产生的原因:

迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。

其实这个问题描述的是:迭代器遍历元素的时候,通过集合是不能修改元素的。

如何解决呢?

A:迭代器迭代元素,迭代器修改元素

元素是跟在刚才迭代的元素后面的。

B:集合遍历元素,集合修改元素(普通for)

元素在最后添加的

解决方案:for循环我就不试了,就用另一种方式解决,代码如下:

public class Test {
		public static void main(String[] args) {
			List<String> list = new ArrayList<String>();

			list.add("java");
			list.add("world");
			list.add("android");
			 ListIterator lit = list.listIterator();
			 while (lit.hasNext()) {
			 String s = (String) lit.next();
			 if ("world".equals(s)) {
			 lit.add("javaee");
			  }
			 }
			 System.out.println(list);
		}
}

因为ListIterator有add()方法 就解决了

时间: 2024-11-06 12:35:55

java 并发操作list集合导致java.util.ConcurrentModificationException的相关文章

Java并发编程(四)Java内存模型

相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Java并发编程(三)volatile域 前言 此前我们讲到了线程.同步以及volatile关键字,对于Java的并发编程我们有必要了解下Java的内存模型,因为Java线程之间的通信对于工程师来言是完全透明的,内存可见性问题很容易使工程师们觉得困惑,这篇文章我们来主要的讲下Java内存模型的相关概念. 1.共享内存和消息传递 线程之间的通信机制有两种:共享内存和消息传递:在共享内存的并发模型里,线程之间共享程序的

死磕Java并发-----J.U.C之Java并发容器:ConcurrentHashMap

HashMap是我们用得非常频繁的一个集合,但是由于它是非线程安全的,在多线程环境下,put操作是有可能产生死循环的,导致CPU利用率接近100%.为了解决该问题,提供了Hashtable和Collections.synchronizedMap(hashMap)两种解决方案,但是这两种方案都是对读写加锁,独占式,一个线程在读时其他线程必须等待,吞吐量较低,性能较为低下.故而Doug Lea大神给我们提供了高性能的线程安全HashMap:ConcurrentHashMap. ConcurrentH

Java并发编程(四)-- Java内存模型

Java内存模型 前面讲到了Java线程之间的通信采用的是共享内存模型,这里提到的共享内存模型指的就是Java内存模型(简称JMM),JMM决定一个线程对共享变量的写入何时对另一个线程可见.从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本.本地内存是JMM的一个抽象概念,并不真实存在.它涵盖了缓存,写缓冲区,寄存器以及其他的

【Java并发专题之二】Java线程基础

使用线程更好的提高资源利用率,但也会带来上下文切换的消耗,频繁的内核态和用户态的切换消耗,如果代码设计不好,可能弊大于利. 一.线程 进程是分配资源的最小单位,线程是程序执行的最小单位:线程是依附于进程的,一个进程可以生成多个线程,这些线程拥有共享的进程资源: 二.线程生命周期(相关API)1.5个阶段6种状态 5个阶段:新建(New).就绪(Runnable).运行(Running).阻塞(Blocked)和死亡(Dead). 6种状态: public enum State { /** * T

Java并发(基础知识)—— Java中断机制

上文讲解了Java线程的创建.启动以及停止,在讲到停止线程时说到了Java中断,Java中断是停止线程的一种协作机制,本文打算对Java中断机制进行详细讲解. 在网上搜索Java中断机制,发现两篇好文章,分别如下:Java 理论与实践: 处理 InterruptedException 以及 详细分析Java中断机制,推荐大家仔细阅读. 中断是一种协作机制 必须记住,中断是一种协作机制.当一个线程中断另一个线程时,被中断的线程不一定要立即停止正在做的事情.相反,中断是礼貌地请求另一个线程在它愿意并

【java并发】(2) Java线程同步:synchronized锁住的是代码还是对象

在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行.synchronized既可以加在一段代码上,也可以加在方法上. 关键是,不要认为给方法或者代码段加上synchronized就万事大吉,看下面一段代码: class Sync { public synchronized void test() { System.out.println("test开始.."); try { Thread.sle

Java并发程序设计(三) Java内存模型和线程安全

Java内存模型和线程安全 一 .原子性 原子性是指一个操作是不可中断的.即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其它线程干扰. 思考:i++是原子操作吗?  二.有序性 Java代码在执行使,并不一点会按照编写程序的语义顺序执行(为了优化性能).具体不做解释. 三.可见性 可见性是指一个线程修改了一个共享变量的值,其他线程能否立即知道这个修改. 编译器优化硬件优化(如写吸收,批操作) Java虚拟机层面的可见性  public class VisibilityTest ext

《Java并发编程的艺术》--Java中的锁

No1: Lock接口 Lock lock = new ReentrantLock(); lock.lock(); try{ }finally{ lock.unlock(); } No2: 不要讲获取锁的过程写在try块中,因为如果在获取锁(自定义锁的实现)时发生了异常,异常抛出的同时,也会导致锁无故释放 No3: No4: 队列同步器(同步器)是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作,并发包的作者期望它能

《Java并发编程实战》第十一章 性能与可伸缩性 读书笔记

造成开销的操作包括: 1. 线程之间的协调(例如:锁.触发信号以及内存同步等) 2. 增加的上下文切换 3. 线程的创建和销毁 4. 线程的调度 一.对性能的思考 1 性能与可伸缩性 运行速度涉及以下两个指标: 某个指定的任务单元需要"多快"才能处理完成.计算资源一定的情况下,能完成"多少"工作. 可伸缩性: 当增加计算资源时(例如:CPU.内存.存储容器或I/O带宽),程序的吞吐量或者处理能力能相应地增加. 2 评估各种性能权衡因素 避免不成熟的优化.首先使程序正