考虑算法:
session.setAttribute("myObject", new Object);
session.setAttribute
HttpSessionAttributeListener#attributeAdded
阻止session.setAttribute
或侦听器代码是否会调用异步?
答案 0 :(得分:3)
在调用set|get|removeAttribute()
的同一个线程中调用侦听器。
因此,在另一个线程中调用setAttribute()
时,可能会出现唯一的竞争条件。假设平均servlet容器使用single thread per HTTP connection(因此当HTTP 1.1 keep-alive
打开时不一定每HTTP请求),那么当最终用户产生两个完全独立的浏览器实例时,可能会出现这种竞争情况(不是windows / tabs)并将会话cookie从一个复制到另一个,然后在该会话中同时触发两个客户端的请求,触发服务器中的setAttribute()
方法。
然而,这不是通常的现实案例。而且,容器本身都会担心访问HttpSession
实例的线程安全性。这在Servlet specification(强调我的)的第7.7.1章中有详细说明:
7.7.1线程问题
执行请求线程的多个servlet可以具有对它的活动访问权限 会话对象同时出现。 容器必须确保操纵 表示会话属性的内部数据结构在线程中执行 安全的方式。开发人员负责线程安全访问 属性对象本身。这将保护内部的属性集合 来自并发访问的
HttpSession
对象,消除了一个机会 应用程序导致该集合损坏。
所以你唯一关心的是属性本身的安全性。例如。如果它是ArrayList
,并且您担心其线程安全,那么您可能希望将其包装在Collections#synchronizedList()
中。
答案 1 :(得分:1)
它是一个SYNC过程。我刚做了一个示例程序。
JSP代码:
<%
session.setAttribute("ID","12324");
session.setAttribute("ID2","656565");
%>
listener CodeAdded of 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