从列表中删除元素时引发ConcurrentModificationException

时间:2018-06-25 22:28:16

标签: codenameone

我必须从存储中迭代的列表中删除该元素。即使使用Iterator,它也会引发ConcurrentModificationException。该代码将在活动结束时执行。请参阅:iter1.remove()。请建议是否有任何解决方法。

List<OfflineCommand> l_loc = (List<OfflineCommand>) Storage.getInstance().readObject("LocationTest"); 
            if (l_loc != null) {                
                boolean flgSuccess = true;
                ListIterator<OfflineCommand> iter1 = l_loc.listIterator();
                while (iter1.hasNext()) {
                    OfflineCommand oc = iter1.next();
                    flgSuccess = executeOfflineCommand(oc);
                    if (!flgSuccess) {
                        break;
                    } else {
                        iter1.remove();
                    }
                }
            }

在另一个地方,我使用下面的代码每分钟将条目添加到同一列表中。

 List<OfflineCommand> l_noAppt = Storage.getInstance().readObject("LocationTest");
            if (l_noAppt == null) {
                l_noAppt = new ArrayList<>();
            }
            l_noAppt.add(new OfflineCommand(name, args));
            Storage.getInstance().writeObject("LocationTest", l_noAppt);

3 个答案:

答案 0 :(得分:1)

在一个位置上添加元素同时在另一个位置上删除需要同步。

A)使用 Vector

Vector提供了开箱即用的同步功能。但是即使对于Vector,也不要使用Iterator ,因为您有并发的修改。

// On the place where you create your list now, create a Vector,
// like ... = new Vector<...>() instead of ... = new ArrayList<...>().
// Just a cast is not sufficient of course.
Vector<OfflineCommand> l_loc = ...;
if (l_loc != null) {                
  boolean flgSuccess = true;
  while (!l_loc.isEmpty()) {
    OfflineCommand oc = l_loc.get(0);
    flgSuccess = executeOfflineCommand(oc);
    if (!flgSuccess) {
      break;
    } else {
      l_loc.remove(0);
    }
  }
}

优点:您不需要显式同步。您的代码保持紧凑。

B)使用显式同步。

List<OfflineCommand> l_loc = ...;
if (l_loc != null) {                
  boolean flgSuccess = true;
  while (!l_loc.isEmpty()) {
    OfflineCommand oc = l_loc.get(0);
    flgSuccess = executeOfflineCommand(oc);
    if (!flgSuccess) {
      break;
    } else {
      synchronized (l_loc) {
        l_loc.remove(0);
      }
    }
  }
}

重要提示:在将对象添加到此列表的位置上,还应该使用同步:

synchronized(l_loc) {
  l_loc.add(...);
}

第二种方法不是那么可靠,因为您应该牢记可以修改列表的所有位置,并在那里使用同步。

A和B这两种方法都可以解决并发修改问题。

答案 1 :(得分:0)

您的问题含糊。 为了避免ConcurrentModificationException,请使用ConcurrentHashMap并使用FOR循环。

答案 2 :(得分:-1)

一旦调用remove()Iterator实例将变为无效。有几种解决方法。由于您删除了所有元素,直到输入不成功为止,类似iter1 = l_loc.listIterator();或在上下文中这样的工作正常:

            while (iter1.hasNext()) {
                OfflineCommand oc = iter1.next();
                flgSuccess = executeOfflineCommand(oc);
                if (!flgSuccess) {
                    break;
                } else {
                    iter1.remove();
                    iter1 = l_loc.listIterator();
                }
            }