繁体   English   中英

Servlet中的java.util.ConcurrentModificationException

[英]java.util.ConcurrentModificationException in a Servlet

编辑:我明白我的错误。 我不知道为什么,但我想在previousItems.add(p);之后previousItems.add(p); 被执行,它从for loop退出。 我已经加入了解决break

有关此异常的其他问题并没有帮助我找到解决方案。

我有一个Servlet ,当我从另一个页面的购物车中添加商品时会调用该Servlet

我有一个ArrayList<Product>并且遍历列表以检查是否要在列表中添加相同的产品。 如果已经存在,则更新其数量,否则,将新产品添加到列表中。

如果总是添加相同的产品,一切都很好,但是当我添加其他产品时会发生异常。 因此,我认为代码中的问题是在else后面(注释为“ This”),因为如果Product不同,则执行该问题。

@WebServlet(name = "AddCart", urlPatterns = {"/AddCart"})
public class AddCart extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        ArrayList<Product> previousItems = (ArrayList<Product>) session.getAttribute("previousItems");
        Product p = (Product) session.getAttribute("currentProduct");
        if (previousItems == null) {
            previousItems = new ArrayList<Product>();
        }

            if (p != null) {
                if (previousItems.size()>0) {
                    for (Product p1 : previousItems) {
                        if (p1.getId() == p.getId()) {
                            p1.addQuantity();
                        } else { //This
                            previousItems.add(p);
                        }
                    }
                } else {
                    previousItems.add(p);
                }
            }

        session.setAttribute("previousItems", previousItems);
        response.sendRedirect("cart.jsp");
    }
}

我也尝试删除synchronized相同异常。

这是HTTP Status 500 – Internal Server Error

java.util.ConcurrentModificationException

java.util.ArrayList $ Itr.checkForComodification(ArrayList.java:901)java.util.ArrayList $ Itr.next(ArrayList.java:851)servlets.AddCart.doGet(AddCart.java:36)javax.servlet.http。 HttpServlet.service(HttpServlet.java:635)javax.servlet.http.HttpServlet.service(HttpServlet.java:742)org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

您无法使用增强的for循环将项目添加到要迭代的列表中。 这是因为您正在修改列表的内部状态。 尽管有可能处理此问题,但是大多数迭代器实现都不处理基础集合的状态更改,以便在绝大多数用例中保持简单。

代替这个:

for (Product p1 : previousItems) {
    previousItems.add(p); // Simplified
}

如果要让p在之后的列表中,请将其放入另一个列表,然后在迭代后添加该列表:

List<Product> other = new ArrayList<>();
for (Product p1 : previousItems) {
    other.add(p);
}
previousItems.addAll(other);

当您在for循环内修改ArrayList时,会出现此异常。 在内部, for循环使用Iterator并且不允许在迭代过程中修改非线程安全的集合。 你可以阅读文章,了解更多信息。

但是,我建议您通过以下方式更改您的逻辑:

if (p != null) {
  // Check if previousItems already contains the product
  if (!previousItems.contains(p)) {
    // If it doesn't, add the product
    previousItems.add(p);
  }
}

您无法更新要迭代的列表,这会导致ConcurrentModificationException

for (Product p1 : previousItems) {
    previousItems.add(p); //you cant update the previousItems list here
}

相反,您可以做的是:

ArrayList<Product> auxList = new ArrayList<>();
for (Product p1 : previousItems) {
    //...
    //else...
        auxList.add(p);
}

之后:

previousItems.addAll(auxList);

如果只想避免ConcurrentModificationException,请使用CopyOnWriteArrayList而不是ArrayList。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM