2016-11-18 57 views
0

我读过很多关于这个问题的SO问题,但我不明白为什么我有一个java.util.ConcurrentModificationException的Android ConcurrentModificationException的上设置

在一类我有这样的:

private Set<RequestOrders> mRequests = new HashSet<>(); 
private final Object lock = new Object(); 

所有操作在mRequest对象通过synchronized声明这样的包围:

public void handleOrder(RequestOrders order) { 
    synchronized (lock) { 
     if (!mRequests.contains(order)) { 
      final sOrder = saveOrderOnDB(order); 
      mRequests.add(sOrder); 

      handleOrder(sOrder; 
     } 
    } 
} 

我得到的错误是:

void notifyOrder(int type) { 
    if (!mPause) { 
     synchronized (lock) { 
      for (RequestOrders request : mRequests) { // Error here while iterating 
       if (.....) { 
        redirectOrders(request); 
       } else if (....) { 
        ...... 
        startService(.....); 
       } 
      } 
     } 
    } else { 
     ..... 
    } 
} 

任何想法为什么?同步语句不应该阻止并发问题吗?

回答

1

它看起来像你的方法调用来添加/删除RequestOrders从集可能正在发生,而你仍然在迭代mRequest集。因此,当你仍然在迭代导致错误时,mRequest集的大小正在改变。要解决这个问题,您可以:

1 - 创建一个临时集,其中包含要添加到mRequest的所有对象。一旦完成循环遍历mRequest集合中的所有对象,请将临时集合中的所有对象添加到mRequest集合中。

2-使用并发HashMap。

这里是你如何使用第一种方法的例子:

private Set<RequestOrders> mRequests = new HashSet<>(); 
private Set<RequestOrders> backlog = new HashSet<>(); 

public void handleOrder(RequestOrders order) { 
    synchronized (lock) { 
     if (!mRequests.contains(order)) { 
      final sOrder = saveOrderOnDB(order); 
      backlog.add(sOrder); 
      handleOrder(sOrder); 
     } 
    } 
} 

void notifyOrder(int type) { 
    if (!mPause) { 
     for (RequestOrders request : mRequests) { // Error here while iterating 
      if (.....) { 
       redirectOrders(request); 
      } else if (....) { 
       ...... 
       startService(.....); 
      } 
     } 
     mRequests.addAll(backlog); 
     backlog.clear(); 
    } else { 
     ..... 
    } 
} 
+0

感谢。我是否应该特别注意删除'mRequests.remove(order);'? – Favolas

+1

是的,对Set的任何修改将导致Set size改变,(remove或add)将需要以类似的方式处理。祝你好运 :) – sparkplug

相关问题