有状态和无状态的对象基本概念:
有状态对象(Stateful Bean),就是有实例变量的对象 ,能够保存数据,是非线程安全的。通常是prototype scope。
无状态对象(Stateless Bean),就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。通常是singleton scope。spring
如Struts2中的Action,假如内部有实例变量User,当调用新增用户方法时,user是用来保存数据,那么此action是有状态对象。多个线程同时访问此action时 会形成user变量的不一致。因此action的scope要设计成prototype,或者,User类放到threadLocal里来保持多个线程不会形成User变量的乱串(此种场景不必放到threadLocal内)。安全
而Service内部通常只有dao实例变量 如userDao, 由于userDao是无状态的对象(内部无实例变量且不能保存数据),因此service也是无状态的对象。多线程
public class XxxAction{less
// 因为多线程环境下,user是引用对象,是非线程安全的 prototype
public User user;线程
......设计
}对象
public class XxxService { blog
// 虽然有billDao属性,但billDao是没有状态信息的,是Stateless Bean. 内存
BillDao billDao;
......
}
对于那些会以多线程运行的单例类
局部变量不会受多线程影响,
成员变量会受到多线程影响。
多个线程调用同一个对象的同一个方法:
若是方法里无局部变量,那么不受任何影响;
若是方法里有局部变量,只有读操做,不受影响;存在写操做,考虑多线程影响值;
例如Web应用中的Servlet,每一个方法中对局部变量的操做都是在线程本身独立的内存区域内完成的,因此是线程安全的。
对于成员变量的操做,能够使用ThreadLocal来保证线程安全。
springMVC中,通常Controller、service、DAO层的scope均是singleton;
每一个请求都是单独的线程,即便同时访问同一个Controller对象,由于并无修改Controller对象,至关于针对Controller对象而言,只是读操做,没有写操做,不须要作同步处理。
Service层、Dao层用默认singleton就行,虽然Service类也有dao这样的属性,但dao这些类都是没有状态信息的,也就是 至关于不变(immutable)类,因此不影响。
Struts2中的Action由于会有User、BizEntity这样的实例对象,是有状态信息 的,在多线程环境下是不安全的,因此Struts2默认的实现是Prototype模式。在Spring中,Struts2的Action中scope 要配成prototype做用域。