相关疑难解决方法(0)

并发修改例外

我目前正在研究一个多线程应用程序,偶尔也会收到一个同时修改的异常(平均大约每小时一次或两次,但是看似随机的间隔).

有缺陷的类本质上是一个map的包装器 - 它扩展了LinkedHashMap(accessOrder设置为true).该类有几个方法:

synchronized set(SomeKey key, SomeValue val)
Run Code Online (Sandbox Code Playgroud)

set方法将键/值对添加到内部映射,并受synchronized关键字的保护.

synchronized get(SomeKey key)
Run Code Online (Sandbox Code Playgroud)

get方法根据输入键返回值.

rebuild()
Run Code Online (Sandbox Code Playgroud)

内部地图偶尔重建一次(〜每2分钟,间隔与异常不匹配).rebuild方法基本上根据键重建值.由于rebuild()相当昂贵,我没有在方法上放置synchronized关键字.相反,我正在做:

public void rebuild(){
  /* initialization stuff */
  List<SomeKey> keysCopy = new ArrayList<SomeKey>();
  synchronized (this) {
    keysCopy.addAll(internalMap.keySet());
  }
  /* 
    do stuff with keysCopy, update a temporary map
   */    
  synchronized (this) {
    internalMap.putAll(tempMap);
  }
}
Run Code Online (Sandbox Code Playgroud)

例外情况发生在

keysCopy.addAll(internalMap.keySet());
Run Code Online (Sandbox Code Playgroud)

在synchronized块内.

建议非常感谢.请随意向我指出Effective Java和/或Concurrency in Practice中的特定页面/章节.

更新1:

消毒堆栈跟踪:

java.util.ConcurrentModificationException
        at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:365)
        at java.util.LinkedHashMap$KeyIterator.next(LinkedHashMap.java:376)
        at java.util.AbstractCollection.toArray(AbstractCollection.java:126)
        at java.util.ArrayList.addAll(ArrayList.java:473)
        at a.b.c.etc.SomeWrapper.rebuild(SomeWraper.java:109)
        at a.b.c.etc.SomeCaller.updateCache(SomeCaller.java:421)
        ...
Run Code Online (Sandbox Code Playgroud)

更新2:

感谢大家到目前为止的答案.我认为问题在于LinkedHashMap及其accessOrder属性,尽管我并不完全确定atm(调查). …

java collections concurrency

8
推荐指数
2
解决办法
1万
查看次数

Java:迭代列表时出现ConcurrentModificationException

当我执行以下代码时,我得到ConcurrentModificationException

 Collection<String> myCollection = Collections.synchronizedList(new ArrayList<String>(10));
    myCollection.add("123");
    myCollection.add("456");
    myCollection.add("789");
    for (Iterator it = myCollection.iterator(); it.hasNext();) {
        String myObject = (String)it.next();
        System.out.println(myObject);
        myCollection.remove(myObject); 
        //it.remove();
    }
Run Code Online (Sandbox Code Playgroud)

为什么我得到异常,即使我使用Collections.synchronizedList?

当我将myCollection更改为

  ConcurrentLinkedQueue<String> myCollection = new ConcurrentLinkedQueue<String>();
Run Code Online (Sandbox Code Playgroud)

我没有得到那个例外.

java.util.concurrent中的ConcurrentLinkedQueue与Collections.synchronizedList有何不同?

java collections

8
推荐指数
2
解决办法
1万
查看次数

java.util.List的异常行为基于其中的元素数量

我知道如果使用迭代器在某个线程遍历它时将更改Collection,则iterator.next()将抛出ConcurrentModificationException.

但它根据列表中的元素数量显示不同的行为.

我尝试了一个代码片段,在其中遍历for-each循环中的列表,在它之间,遍历使用列表的remove()方法从列表中删除了一个元素.

理想情况下,它应该在此条件下抛出ConcurrentModificationException而不依赖于列表中的元素数量,但是当列表中的元素数量为2时,它不是真的.

案例1: 列表中的元素数量 - 1

 public static void main(String[] args) 
    {
        List<String> list=new ArrayList<String>();
        list.add("One");

        for (String string : list) 
        {
            System.out.println(string);
            list.remove(string);
        }
    }
Run Code Online (Sandbox Code Playgroud)

输出:一

线程"main"java.util.ConcurrentModificationException中的异常

这是预期的.

案例2:列表中的元素数量 - 2

 public static void main(String[] args) 
    {
        List<String> list=new ArrayList<String>();
        list.add("One");
        list.add("two");

        for (String string : list) 
        {
            System.out.println(string);
            list.remove(string);
        }
    }
Run Code Online (Sandbox Code Playgroud)

输出:一

没有例外被抛出?????????

案例3:列表中的元素数量 - 3

 public static void main(String[] args) 
    {
        List<String> list=new ArrayList<String>();
        list.add("One");
        list.add("Two");
        list.add("Three");

        for (String string …
Run Code Online (Sandbox Code Playgroud)

java collections iterator list concurrentmodification

8
推荐指数
2
解决办法
292
查看次数

如何避免ConcurrentModificationException

每当我们使用java.util Collection类时,我们就知道如果一个线程更改了一个集合,而另一个线程使用迭代器遍历它,那么任何调用iterator.hasNext()iterator.next()将抛出ConcurrentModificationException.即使是synchronized集合包装类SynchronizedMapSynchronizedList仅有条件线程安全的,这意味着所有的个别操作都是线程安全的,但复合操作,其中的控制流取决于前面操作的结果可能会受到线程问题.问题是:如何在不影响性能的情况下避免此问题.注意:我知道CopyOnWriteArrayList.

java collections concurrency

7
推荐指数
1
解决办法
2835
查看次数

清除子列表时出现ConcurrentModificationException

ConcurrentModificationExcrption当我清除主列表后的子列表时,为什么以下代码抛出,但如果我清除子列表然后清除主列表则不会?

ArrayList<Integer> masterList = new ArrayList<Integer>();
List<Integer> subList;

// Add some values to the masterList
for (int i = 0; i < 10; i++) {
    masterList.add(i * i);
}

// Extract a subList from the masterList
subList = masterList.subList(5, masterList.size() - 1);

// The below throws ConcurrentModificationException
masterList.clear();
subList.clear(); // Exception thrown in this line

// The below doesn't throw any exception
subList.clear();
masterList.clear(); // No exception thrown. Confused??
Run Code Online (Sandbox Code Playgroud)

java list

7
推荐指数
1
解决办法
1067
查看次数

在Java中,如何在单线程程序中抛出ConcurrentModificationException?

我正在阅读这个" Freuqent Java并发问题 "的问题,并且在谈论java.util.ConcurrentModificationException的答案时感到困惑.

我对答案的理解是,这可能发生在单线程程序中.如何或什么条件导致以下代码抛出异常?

List<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
for (String string : list) { list.remove(string); }
Run Code Online (Sandbox Code Playgroud)

java concurrency concurrentmodification

6
推荐指数
1
解决办法
3502
查看次数

Java ConcurrentModificationException

删除第二个最后一个元素时,没有ConcurrentModificationException

List<String> myList1 = new ArrayList<String>();
Collections.addAll(myList1, "str1","str2","str3","str4","str5");
for(String element : myList1){//no ConcurrentModificationException here
if(element.equalsIgnoreCase("str4"))
    myList1.remove("str4");
}
System.out.println(myList1);
Run Code Online (Sandbox Code Playgroud)

但是当删除其他元素时会出现ConcurrentModificationException

List<String> myList2 = new ArrayList<String>();
Collections.addAll(myList2, "str1","str2","str3","str4","str5");
for(String element : myList2){//ConcurrentModificationException here
if(element.equalsIgnoreCase("str1"))
    myList2.remove("str1");
}
System.out.println(myList2);
Run Code Online (Sandbox Code Playgroud)

是什么原因?

java exception

6
推荐指数
1
解决办法
1040
查看次数

ConcurrentModificationException甚至在LinkedHashMap上使用Collections.sychronizedMap

我在我的类中使用了一个Map对象,我已经与LinkedHashMap的Collections.synchronizedMap()同步,如下所示:

private GameObjectManager(){
        gameObjects = Collections.synchronizedMap(new LinkedHashMap<String, GameObject>());
}
Run Code Online (Sandbox Code Playgroud)

我在这个函数的第三行得到一个并发修改异常:

public static void frameElapsed(float msElapsed){
    if(!INSTANCE.gameObjects.isEmpty()){
        synchronized(INSTANCE.gameObjects){
            for(GameObject object : INSTANCE.gameObjects.values()){...}
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在迭代Map的所有其他位置,我按照文档同步地图.

我的类中还有其他函数使用这个Map(同步的!)和put()和remove()对象,但这应该无关紧要.我究竟做错了什么?请询问更多代码,不知道还能提供什么.

哦,和日志消息:

08-20 15:55:30.109: E/AndroidRuntime(14482): FATAL EXCEPTION: GLThread 1748
08-20 15:55:30.109: E/AndroidRuntime(14482): java.util.ConcurrentModificationException
08-20 15:55:30.109: E/AndroidRuntime(14482):    at     java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:350)
08-20 15:55:30.109: E/AndroidRuntime(14482):    at     java.util.LinkedHashMap$ValueIterator.next(LinkedHashMap.java:374)
08-20 15:55:30.109: E/AndroidRuntime(14482):    at     package.GameObjectManager.frameElapsed(GameObjectManager.java:247)
08-20 15:55:30.109: E/AndroidRuntime(14482):    at     package.GamekitInterface.render(Native Method)
08-20 15:55:30.109: E/AndroidRuntime(14482):    at     package.GamekitInterface.renderFrame(GamekitInterface.java:332)
08-20 15:55:30.109: E/AndroidRuntime(14482):    at     com.qualcomm.QCARSamples.ImageTargets.GameEngineInterface.onDrawFrame(GameEngineInterface.java:107)
08-20 15:55:30.109: E/AndroidRuntime(14482):    at     android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
08-20 15:55:30.109: E/AndroidRuntime(14482):    at     android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
Run Code Online (Sandbox Code Playgroud)

java multithreading synchronized linkedhashmap concurrentmodification

5
推荐指数
1
解决办法
3282
查看次数

为什么在这种情况下没有使用LinkedList迭代器的ConcurrentModificationException?

请考虑以下代码段:

List<String> list = new LinkedList<>();
list.add("Hello");
list.add("My");
list.add("Son");

for (String s: list){
    if (s.equals("My")) list.remove(s);
    System.out.printf("s=%s, list=%s\n",s,list.toString());
}
Run Code Online (Sandbox Code Playgroud)

这导致输出:

s = Hello,list = [Hello,My,Son]
s = My,list = [Hello,Son]

很明显,循环只输入两次,第三个元素"Son"永远不会被访问.从底层的库代码中,看起来发生的是hasNext()迭代器中的方法不检查并发修改,只检查下一个索引的大小.由于remove()调用后大小减少了1 ,因此循环不会再次输入,但不会抛出ConcurrentModificationException.

这似乎与迭代器的契约相矛盾:

list-iterator是快速失败的:如果在创建Iterator之后的任何时候对列表进行结构修改,除了通过list-iterator自己的removeadd方法之外,list-iterator将抛出一个ConcurrentModificationException.因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒任意,非确定性行为的风险.

这是一个错误吗?同样,迭代器的契约在这里看起来肯定是不服从的 - 列表的结构在迭代过程中由迭代器之外的其他东西进行结构修改.

java linked-list

5
推荐指数
1
解决办法
326
查看次数

访问hashmap时出现java.util.ConcurrentModificationException

为什么发生以下异常?

2012-08-28 11:41:59,183 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/TFO].[tfo]] (http-0.0.0.0-8080-9) Servlet.service() for servlet tfo threw exception: java.util.ConcurrentModificationException
            at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) [:1.6.0_24]
            at java.util.HashMap$EntryIterator.next(HashMap.java:834) [:1.6.0_24]
            at java.util.HashMap$EntryIterator.next(HashMap.java:832) [:1.6.0_24]
            at net.sf.json.JSONObject._fromMap(JSONObject.java:1082) [:]
            at net.sf.json.JSONObject.fromObject(JSONObject.java:173) [:]
            at net.sf.json.JSONObject._processValue(JSONObject.java:2552) [:]
Run Code Online (Sandbox Code Playgroud)

java collections exception hashmap

2
推荐指数
1
解决办法
6723
查看次数