【问题标题】:Thread safety with CopyOnArrayList in servletservlet 中 CopyOnArrayList 的线程安全
【发布时间】:2016-02-03 10:04:47
【问题描述】:

我刚开始使用 servlet 和线程。最终实例变量是线程安全的,CopyOnArrayList 也是如此。为什么下面的代码不是线程安全的(它是最终的 + 我使用了 CopyOnArrayList)?

@WebServlet("/index.html")
public class CatServlet extends HttpServlet {
    private final static long serialVersionUID = 1L;
    private final static String VIEW = "/WEB-INF/JSP/index.jsp";
    **private final CopyOnWriteArrayList <Cat> l = new CopyOnWriteArrayList<>();**

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        l.add(new Cat("Dean", 7));
        l.add(new Cat("Sam", 7));
        l.add(new Cat("Pixie", 0));
        request.setAttribute("catList", l);
        request.getRequestDispatcher(VIEW).forward(request, response);
    }

JSP 代码:

<c:forEach var="cat" items="${catList}" >
    <li>${cat.name}</li>
</c:forEach>

首先我得到 3 个 Cat 实例。刷新时我得到 6,然后是 9、12,等等。为什么? 当我在 doGet 方法中声明 CopyOnWriteArrayList 或使用简单数组时,不会出现此问题。我不明白它背后的逻辑:最终实例变量和 CopyOnWriteArrayList 应该是线程安全的。谢谢大家澄清这一点。

【问题讨论】:

    标签: java multithreading jsp servlets copyonwritearraylist


    【解决方案1】:

    自从您在 doGet 方法中添加它们以来,每次刷新页面时,您都会在列表中添加 3 个元素。

    如果您在doGet 方法中声明您的列表,则每次调用该方法时它都会被删除。

    这里不涉及线程安全。

    【讨论】:

      【解决方案2】:

      它是CopyOnWriteArrayList,而不是EraseOnWriteArrayListCopyOnWriteArrayList 每次写入时都会创建一个新副本,以便现有的迭代器继续在旧版本上运行。每次调用 doGet 时都不会删除该列表,因此它只是添加到末尾。每次添加新的Cat 时,您都会有不必要的内部复制开销。

      【讨论】:

        猜你喜欢
        • 2016-08-24
        • 2012-02-10
        • 1970-01-01
        • 2010-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多