中富国建设有限公司网站,iis5.1 新建网站,安徽seo报价,wordpress 企业整站源码迭代器生成器可迭代对象Java Collection类是快速失败的#xff0c;这意味着如果在使用迭代器遍历某个线程的同时更改了Collection#xff0c;则iterator.next#xff08;#xff09;将抛出ConcurrentModificationException 。 在多线程以及单线程环境中都可能出现这种情况。… 迭代器生成器可迭代对象 Java Collection类是快速失败的这意味着如果在使用迭代器遍历某个线程的同时更改了Collection则iterator.next将抛出ConcurrentModificationException 。 在多线程以及单线程环境中都可能出现这种情况。 让我们通过以下示例探索这种情况 import java.util.*;public class IteratorExample {public static void main(String args[]){ListString myList new ArrayListString();myList.add(1);myList.add(2);myList.add(3);myList.add(4);myList.add(5);IteratorString it myList.iterator();while(it.hasNext()){String value it.next();System.out.println(List Value:value);if(value.equals(3)) myList.remove(value);}MapString,String myMap new HashMapString,String();myMap.put(1, 1);myMap.put(2, 2);myMap.put(3, 3);IteratorString 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) {ListString myList new CopyOnWriteArrayListString();myList.add(1);myList.add(2);myList.add(3);myList.add(4);myList.add(5);IteratorString 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());MapString,String myMap new ConcurrentHashMapString,String();myMap.put(1, 1);myMap.put(2, 2);myMap.put(3, 3);IteratorString 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; imyList.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迭代器生成器可迭代对象