使用迭代器时获取java.util.LinkedList $ ListItr.checkForComodification异常?

时间:2015-01-18 11:26:48

标签: java multithreading concurrency iterator

我正在使用listIterator()来访问和删除实现LinkedList的类中Runnable的项目我同时也在程序的其他部分修改此列表的值

我在代码的这一部分使用listIterator()的地方我从这个函数调用中获取ConcurrentModificationException

java.util.LinkedList中$ ListItr.checkForComodification

为什么我得到这个以及如何预防?

    @Override
    public void run()
    {

        while(true)
        {
            itr = nodeAttributes.listIterator();

            while (itr.hasNext()) 
            {
                System.out.println("enterred");
                nodeAttribute nA = (nodeAttribute) itr.next();
                //System.out.println("for");
                 if(!nA.isMoving && !nA.moveQueue.isEmpty())
                 {
                     if(animator != null)
                         animator.stop();

                     animator = (Animator) nA.moveQueue.poll();
                     //itr.remove();
                     animator.start();
                     nA.isMoving = true;
                     System.out.print( "animator");
                 }
            }
            System.out.println( "looping");

        }
    }

1 个答案:

答案 0 :(得分:3)

你的帖子没有问题,只是一个声明。然而,您所描述的是预期的行为。来自the docs

  

此类的iterator和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时候对列表进行结构修改,除了通过Iterator自己的remove或add方法之外,迭代器将抛出一个ConcurrentModificationException的。

因此,为了防止这种情况,您需要在读者迭代的同时防止编写者进行修改。使用Collections.synchronizedList方法。所有访问(读者和作者)都应遵循以下模式:

// store a single synchronized list reference for all access to use
nodeAttributes = Collections.synchronizedList(theLinkedList);

然后所有读者和作者都应使用synchronized (list)块。

// Readers might do:
synchronized (list) {
  itr = nodeAttributes.listIterator();
  while (i.hasNext())
      ... do stuff ...
}

那些在没有迭代的情况下运行的线程只能在Collections.synchronizedList的返回对象上使用“原子”方法,例如add。这些方法在封面下使用同步块,所以它们只是一个简写,它们仍然会阻塞线程而另一个在同步块中。

处理并发读者和作者的方法有很多种。

  1. 一个是上面的,但它可能会锁定其他线程很长一段时间,而每个迭代器做它的东西。
  2. 另一种方法是将列表复制到一个数组(在同步部分内),然后读取锁外的数组。
  3. 另一种方法是使用ReadWriteLock
  4. 还有更多选项,全部取决于您的确切用例。