servlet 中 CopyOnArrayList 的线程安全
Thread safety with CopyOnArrayList in servlet
我刚开始学习 servlet 和线程。 Final 实例变量是线程安全的,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 应该是线程安全的。谢谢大家的澄清。
您每次刷新页面时都会在列表中添加 3 个元素,因为您是在 doGet
方法中添加的。
如果您在 doGet
方法中声明列表,则每次调用该方法时都会将其删除。
这里不涉及线程安全。
是CopyOnWriteArrayList
,不是EraseOnWriteArrayList
。 CopyOnWriteArrayList
每次写入都会创建一个新的副本,以便现有的迭代器继续在旧版本上运行。每次调用 doGet 时都不会删除该列表,因此它只是在最后添加。每次添加新的 Cat
.
时,您只会有不必要的内部复制开销
我刚开始学习 servlet 和线程。 Final 实例变量是线程安全的,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 应该是线程安全的。谢谢大家的澄清。
您每次刷新页面时都会在列表中添加 3 个元素,因为您是在 doGet
方法中添加的。
如果您在 doGet
方法中声明列表,则每次调用该方法时都会将其删除。
这里不涉及线程安全。
是CopyOnWriteArrayList
,不是EraseOnWriteArrayList
。 CopyOnWriteArrayList
每次写入都会创建一个新的副本,以便现有的迭代器继续在旧版本上运行。每次调用 doGet 时都不会删除该列表,因此它只是在最后添加。每次添加新的 Cat
.