ConcurrentModificationException,无需修改对象

时间:2014-03-20 10:24:17

标签: java playframework-2.0 concurrentmodification

我得到了以下导致ConcurrentModificationException的代码。我根本没有修改products对象,

List<Product> products = Product.findActiveByFilter(filters);
Set<Long> temp = new HashSet<Long>();
List<Product> resultSetTemp = new ArrayList<Product>();
for (Product product : products) { // << Exception points to this
    if(!temp.contains(product.getId())){
        temp.add(product.getId());
        resultSetTemp.add(product);
    }
}
products.clear();
products.addAll(resultSetTemp);

我已多次看到此异常弹出窗口,但我无法重现它(它随机发生)。

Product.findActiveByFilter是一种方法,它返回已从缓存的List<Product>构建的List<Product>的新实例。

编辑:我找到了重现错误的方法。当客户想要产品(它是网上商店)时,代码被调用,当客户端向下滚动时,网站会加载更多项目。这会触发异常(因为服务器尚未完成对产品的响应,并获得另一个调用)。比赛条件,好玩!

2 个答案:

答案 0 :(得分:1)

正如一些人已经说过的那样,它是由一个单独的'修改'products引起的(因为它是一个缓存的实例)。 我没有更改Product.findActiveByFilter的实现,而是在没有应用过滤器的情况下返回new ArrayList<Product>(products);而不是对缓存值的引用(因此没有给出过滤结果)。

public static List<Product> findActiveByFilter(ArrayList<FilterPair> filters) {
    List<Product> products = getCachedAllProductsByFirstSupplier();

    if (products == null) {
        products = new ArrayList<Product>();
    }

    if(filters.size() > 0) {
        List<Product> productsFiltered = new ArrayList<Product>(products);
        // ... MANY checks here for the filters ...

        return productsFiltered;
    }

    return new ArrayList<Product>(products); // Do not give cached copy, was 'return products;'
}

有两次调用findActiveByFilter,由网站调用。第一个包括一个过滤器,但第二个没有(所以第一个仍然很忙,而第二个直接返回)。

答案 1 :(得分:0)

您是否尝试过使用迭代器?

List<Product> products = Product.findActiveByFilter(filters);
Set<Long> temp = new HashSet<Long>();
List<Product> resultSetTemp = new ArrayList<Product>();

Iterator ite = products.iterator();

while (ite.hasNext()) {

    Product product = ite.next();

    if(!temp.contains(product.getId())){

        temp.add(product.getId());
        resultSetTemp.add(product);
    }
}
products.clear();
products.addAll(resultSetTemp);

编辑:刚看到您的更新。鉴于此,这可能无法解决您的问题。