I've got the following piece of code that is causing a ConcurrentModificationException. I'm not modifying the products
object at all,
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);
I've seen this exception pop-up several times, but I cannot reproduce it (it happens randomly).
Product.findActiveByFilter
is a method that returns a new instance of a List<Product>
that has been build from a cached List<Product>
.
Edit: I've found a way to reproduce the error. The code is called when a client wants the products (its a webshop), and the website loads more items when the client scrolls down. This triggers the exception (as the server is not-yet done responding with the products, and gets another call for it). Race conditions, fun!
As some said already, it was caused by a seperate tread 'modifying' products
(as it was a cached instance).
I've changed the implementation of Product.findActiveByFilter
to return a new ArrayList<Product>(products);
instead of a reference to the cached value, when no filters are applied (thus no filtered result is given back).
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;'
}
There were 2 calls to the findActiveByFilter, called by the website. The first one did include a filter, but the second one did not (so the first one was still busy, while the second one returned directly).