`
jarbee
  • 浏览: 28238 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

单线程情况下遍历ArrayList的ConcurrentModificationException的问题

    博客分类:
  • java
阅读更多
    看到一段程序在单线程方式下运行还抛出ConcurrentModificationException,大概看了下是在以for-each方式遍历ArrayList时,循环内部又对集合作修改引起,换种方式遍历即可解决。
   所以在使用JDK集合类的Iterator时,还要对其实现原理有大概了解。由于一直都没有了解集合遍历,标记下><
code:
@Test
	public void testConcurrentModificationException() throws Exception {
		try {
			List<String> arr = new ArrayList<String>();
			arr.add("1");arr.add("2");arr.add("3");
			
			/* 不会抛出ConcurrentModificationException,
			 * 可在单线程情况下使用此遍历方式
			 */
			for(int i=0; i<arr.size(); i++) {
				arr.add("4");
				if(i==1)
					break;
			}
			System.out.println(arr);
			
			/* 抛出ConcurrentModificationException,
			 * 因为for-each内部以Iterator方遍历集合, 
			 * 由ArrayList创建的Iterator是以快速失败的方式处理遍历过程中的并发修改问题 
			 * @see: java.util.AbstractList.Itr.next()
			 */
			for(String i : arr) {
				arr.add("4");
				if(i.equals("2"))
					break;
			}
			System.out.println(arr);
		} catch(Exception e) {
			e.printStackTrace();
			Assert.fail();
		}
	}

运行结果
[1, 2, 3, 4, 4]
java.util.ConcurrentModificationException
	at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
	at java.util.AbstractList$Itr.next(AbstractList.java:343)
	at com.ys.kj.service.impl.UpgradeServiceTest.testConcurrentModificationException(UpgradeServiceTest.java:57)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
分享到:
评论

相关推荐

    遍历并批量删除容器中元素出现ConcurrentModificationException原因及处置

    这个问题在单线程环境下不会出现,但在多线程并发场景下,如果多个线程同时修改一个集合,就可能导致`ConcurrentModificationException`。 标题中提到的“遍历并批量删除容器中元素”是引发此异常的一个典型操作。...

    Java中ArrayList和Vector的区别共2页.p

    - ArrayList和Vector的迭代器在遍历元素时性能相近,但因为Vector的线程安全性,如果在迭代过程中其他线程修改了Vector,迭代器会抛出`ConcurrentModificationException`,而ArrayList则不会。 6. **使用场景**: ...

    Iterator遍历过程中list删除导致异常

    这个异常通常发生在多线程环境下对共享数据进行并发修改,但即使在单线程情况下,如果在迭代期间调用集合的`add`, `remove`或其他改变结构的方法,也会引发此异常。 `ConcurrentModificationException`并不是由线程...

    程序员面试宝典 java.pdf,这是一份不错的文件

    【何时使用HashMap与Hashtable】在单线程环境中,或者不需要线程安全的情况下,推荐使用HashMap,因为它提供了更好的性能。当需要线程安全时,例如在多线程应用中,应使用Hashtable。此外,如果需要按特定顺序遍历...

    多线程中使用Java集合类.doc

    这意味着在多线程环境下,当一个线程正在遍历集合(通过迭代器进行)时,另一个线程修改了集合内容,就会触发快速失败(fail-fast)机制,导致ConcurrentModificationException异常。例如,上述代码中,线程在删除...

    Collection 详细案例,集合的详细例子,list例子和详细解析,map详细例子和详细解析,set详细列子和详细解析,

    然而,由于其同步性质,Vector在单线程环境中的性能可能不如ArrayList。案例会对比ArrayList和Vector的使用,以及如何在需要线程安全时选择Vector。 Map接口是键值对的集合,最常用的实现包括HashMap、TreeMap等。...

    Java中List集合的遍历实例详解

    索引遍历不会锁定数据,因此在性能上优于迭代器遍历,但在多线程环境下,如果存在并发修改集合的操作,需要额外处理线程安全问题。 在实际应用中,选择哪种遍历方式取决于具体的需求。如果需要线程安全且对性能...

    java-大数据基础面试思考.pdf

    快速失败机制的迭代器是为单线程设计的,因为它们不能保证在并发修改下行为的一致性。 而与快速失败迭代器相对的是故障安全(Fail-Safe)迭代器。故障安全迭代器在迭代过程中不会抛出...

    集合框架面试题.pdf

    而ArrayList在单线程环境下使用效率较高,但多线程环境下需要程序员自己解决线程同步问题。 - 数据增长策略:当ArrayList或Vector的元素数量超出其容量时,它们会自动扩容。Vector默认扩容为原来的两倍,而...

    (完整版)Java集合类.ppt

    然而,这种同步性也降低了性能,因此在单线程环境中通常推荐使用ArrayList。 Set接口: Set接口代表不包含重复元素的集合。HashSet是最常见的Set实现,它基于哈希表,提供快速的插入和查找,但不保证元素的顺序。...

    Java 多线程与并发(14-26)-JUC集合- CopyOnWriteArrayList详解.pdf

    在非并发集合如`ArrayList`中,当多个线程共享集合时,如果一个线程修改了集合的状态(例如添加或删除元素),而此时其他线程正在遍历这个集合,那么后者可能会遇到不一致的数据结构,甚至抛出`...

    java方向各阶段重点知识点 .docx

    ArrayList非线程安全,但在单线程环境下性能优于Vector。 6. **Collection和Collections的区别**:Collection是所有集合类的父接口,包含单列集合的常用方法。Collections是工具类,提供了一系列静态方法,用于操作...

    Java并发编程实践分享PPT教案学习.pptx

    `ArrayList`是非线程安全的,而`Vector`是线程安全的,但在多线程环境下,直接在遍历过程中修改容器可能会导致`ConcurrentModificationException`。这两种容器在并发编程中应谨慎使用,更推荐使用`Collections....

    Java后端资料,面试题,后端知识点

    3. **快速失败与安全失败**:快速失败(fail-fast)是指迭代器在检测到集合结构被修改时立即抛出`ConcurrentModificationException`,而安全失败(fail-safe)的迭代器如`CopyOnWriteArrayList`,在遍历时不会抛出...

    java-collection-all-in-one.pdf

    Java集合框架是Java编程语言中...总之,Java集合框架提供了丰富而强大的数据结构实现,能够满足从单线程到多线程环境下的各种数据管理需求。理解和掌握这些集合的特性、优势和使用场景,对于高效编写Java程序至关重要。

    名企AI面试100题1

    在`for循环`中直接删除ArrayList的元素可能导致ConcurrentModificationException,因为ArrayList的迭代器不支持在遍历过程中修改集合。解决方法是使用`Iterator`来删除元素,或者使用`List.removeIf()`方法,或者在...

    Java面试题集合部分.docx

    13. **并发安全的HashMap**:在多线程环境下,`HashMap`不是线程安全的,此时可以使用`ConcurrentHashMap`。在JDK1.7中,`ConcurrentHashMap`采用锁分段机制,每个段是独立可锁的,提高了并发性能。在JDK1.8中,`...

    阿里巴巴Java开发代码规约

    - 避免使用静态集合类在多线程环境下,可能导致线程安全问题。 6. **集合操作**: - 避免在循环中调用`add`、`remove`等修改集合的方法,可能导致`ConcurrentModificationException`。 - 使用`List`时,尽量使用...

    阿里必问200试题.docx

    7. Java中操作字符串的类有String、StringBuilder和StringBuffer,String是不可变的,StringBuilder和StringBuffer是可变的,后者在多线程环境下更安全。 8. `String str="i"`和`String str=new String("i")`不同,...

Global site tag (gtag.js) - Google Analytics