有状态对象
普通的java类, 都带有属性, 并且属性是可以被修改的,有修改属性值的set方法, 那么这个类的实例就是有状态对象。不同的线程拿到的这个实例, 可能做不同的修改,那么有状态的对象是线程不安全的,对于线程不安全的对象适合多例模式,相当于每个线程都维护了一个有状态的对象。
无状态对象
普通java类,不带有属性,或者带有属性但是属性是不能修改的(例如:注入的一个bean),也没有提供修改的方法,那么这个类的实例就是无状态对象。不同的线程拿到的实例是一样的,不能对实例做修改,那么无状态对象是线程安全的,对于线程安全的无状态对象适合单例模式。
spring框架中有状态对象如何多线程安全?
spring框架有一个scope的概念,分别有singleton,prototype,request,session等值,scope指的是一个对象的生命周期,如果scope=singleton表示容器创建对象时是单态模式,整个容器中只会有一个该类型的对象;如果scope=prototype表示容器创建对象时是多态模式,面对请求每次都会创建一个新的对象。
根据有状态对象和无状态对象的特点,我们可以知道无状态对象在web应用中是singleton单态模式/单例模式,有状态对象是prototype多态模式。
Spring框架中bean的默认scope=singleton,SpringMVC应用针对每次请求的上下文RequestContextHolder的成员变量RequestAttributes会因请求变化而不一样,如此,请求上下文RequestContextHolder就是有状态的对象,因为多线程不安全,有状态的对象适合prototype模式,那RequestContextHolder需要改为prototype吗?。答案是不需要,为什么呢?原来spring针对一些有状态的线程不安全的Bean例如:RequestContextHolder,TransactionSynchronizationManager,LocalContextHolder采用了ThreadLocal处理,让它们变成在多线程安全,因为多线程安全,所以RequestContextHolder不需要采用scope=prototype。
没有经过ThreadLocal处理的有状态的bean,在多线程中使用,还是需要声明scope=prototype才安全。
个人总结,如有不妥,还望指正