【问题标题】:Is HttpSessionAttributeListener processed async?HttpSessionAttributeListener 是异步处理的吗?
【发布时间】:2016-01-21 08:58:49
【问题描述】:

考虑算法:

  1. 一个新属性被添加到会话session.setAttribute("myObject", new Object);
  2. HttpSessionAttributeListener#attributeAdded 被调用
  3. session.setAttribute 之后的代码

HttpSessionAttributeListener#attributeAdded 是否阻塞 session.setAttribute 或侦听器代码调用异步?

【问题讨论】:

    标签: java session servlets listener


    【解决方案1】:

    在调用set|get|removeAttribute() 的同一线程中调用侦听器。

    因此,当在另一个线程中调用 setAttribute() 时,可能会发生唯一的竞争条件。鉴于一般的 servlet 容器使用 single thread per HTTP connection(因此当 HTTP 1.1 keep-alive 开启时不一定每个 HTTP 请求),那么当最终用户产生两个完全独立的浏览器实例(不是窗口/选项卡)时,可能会发生这种竞争情况并将会话 cookie 从一个复制到另一个,然后同时从该会话上的两个客户端触发请求,从而触发服务器中的 setAttribute() 方法。

    然而,这不是一个常见的现实世界案例。此外,容器本身会担心访问HttpSession 实例的线程安全性。这在Servlet specification(强调我的)的第 7.7.1 章中有规定:

    7.7.1 线程问题

    执行请求线程的多个 servlet 可以对同一个线程进行主动访问 同时会话对象。 容器必须确保操纵 表示会话属性的内部数据结构在线程中执行 安全的方式。 开发人员有责任确保线程安全地访问 属性对象本身。这将保护内部的属性集合 HttpSession 对象从并发访问,消除机会 应用程序导致该集合损坏。

    因此,您唯一关心的是属性本身的威胁安全性。例如。如果它是ArrayList,并且您担心它的线程安全,您可能希望将其包装在Collections#synchronizedList() 中。

    【讨论】:

      【解决方案2】:

      它是一个同步过程。我刚刚做了一个示例程序。

      JSP 代码:

      <%
      session.setAttribute("ID","12324");
      session.setAttribute("ID2","656565");
      %>
      

      attributeAdded()方法的监听代码:

      String attributeName = event.getName();
              Object attributeValue = event.getValue();
              System.out.println("Attribute added : " + attributeName + " : " + attributeValue);
              try {
                  Thread.sleep(10000);
              } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
              System.out.println("After Sleep : "+attributeName);
      

      输出:

      Attribute added : ID : 12324
      After Sleep : ID
      Attribute added : ID2 : 656565
      After Sleep : ID2
      

      所以你可以看到,只有在为第一个 id 打印“After Sleep”之后,它才会在会话中添加第二个 id

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-16
        • 1970-01-01
        • 2020-09-26
        • 2016-08-08
        • 1970-01-01
        • 1970-01-01
        • 2019-08-29
        • 2018-05-31
        相关资源
        最近更新 更多