单例、多例与线程安全问题

单例与多例问题是指,当多个用户访问某个类时,系统是为每个用户创建一个该类实例,还是整个系统无论多少用户访问,只创建一个该类实例。

线程安全问题是指,多个用户同时在访问同一个程序时,其对于某一数据的修改,会不会影响到其他用户中的该数据。若无影响,则是线程安全的;若有可能影响,则是线程不安全的。

现在对HttpServlet、HttpSession、Struts2中的Action、Hibernate中的SessionFactory与Session,进行总结。

(1)HttpServlet
单例。即无论多少用户访问同一个业务,如LoginServlet,Web容器只会创建一个该Servlet实例。而该实例是允许多用户访问的。
若Servlet中包含成员变量,则每个用户对于成员变量的修改,均会影响到其他用户所看到的该变量的值,所以这时是线程不安全的。若不包含成员变量,则是线程安全的。

(2)HttpSession
多例。Web容器会为每个用户开辟一个Session,多个用户会有多个Session。而每个用户只能访问自己的Session。所以,对于Session来说,就不存在并发访问的情况,也就不存在线程安全的问题了。所以可以说是线程安全的。

(3)Struts2的Action
多例。对于同一个业务,例如LoginAction,系统会为每一个用户创建一个LoginAction的实例,并使其成员变量username与password接收用户提交的数据。同一用户只能访问自己的Action。所以,对于Action来说,就不存在并发访问的情况,也就不存在线程安全的问题了。所以可以说是线程安全的。

(4)Hibernate的SessionFactory
单例。无论多少用户访问该项目,系统只会创建一个SessionFactory对象,即这个对象是可以被所有用户访问的。
SessionFactory实现类中所包含的成员变量基本都是final常量,即任何用户均不能修改。所以,也就不存在用户的修改对其他用户的影响问题了,所以是线程安全的。

(5)Hibernate的Session
多例。系统会为每个用户创建一个Session。
Session的实现类中定义了很多的非final成员变量,一个事务对成员变量所做的修改,会影响到另一个事务对同一数据的访问结果,所以是线程不安全的。