1.有狀態(Stateful):
有數據存儲功能。有狀態對象(Stateful Bean),就是有實例變量的對象,可以保存數據,類里面有成員變量,而且成員變量是可變的,是非線程安全的。在不同方法調用間不保留任何狀態。
2.無狀態(Stateless):
一次操作,不能保存數據。無狀態對象(Stateless Bean),就是沒有實例變量的對象.不能保存數據,類里面沒有成員變量,或者有成員變量但是不可變的、或者成員變量是單例的,是不變類,是線程安全的。
3.Spring中的有狀態(Stateful)和無狀態(Stateless)
(1).通過上面的分析,相信大家已經對有狀態和無狀態有了一定的理解。無狀態的Bean適合用不變模式,技術就是單例模式,這樣可以共享實例,提高性能。有狀態的Bean,多線程環境下不安全,那么適合用Prototype原型模式。Prototype: 每次對bean的請求都會創建一個新的bean實例。
(2).默認情況下,從Spring bean工廠所取得的實例為singleton(scope屬性為singleton),容器只存在一個共享的bean實例。
(3).理解了兩者的關系,那么scope選擇的原則就很容易了:有狀態的bean都使用prototype作用域,而對無狀態的bean則應該使用singleton作用域。
(4).如Service層、Dao層用默認singleton就行,雖然Service類也有dao這樣的屬性,但dao這些類都是沒有狀態信息的,也就是相當於不變(immutable)類,所以不影響。Struts2中的Action因為會有User、BizEntity這樣的實例對象,是有狀態信息的,在多線程環境下是不安全的,所以Struts2默認的實現是Prototype模式。在Spring中,Struts2的Action中,scope要配成prototype作用域。
4.Servlet、Struts中的有狀態和無狀態:
(1).Servlet體系結構是建立在Java多線程機制之上的,它的生命周期是由Web 容器負責的。一個Servlet類在Application中只有一個實例存在,也就是有多個線程在使用這個實例。這是單例模式的應用。無狀態的單例是線程安全的,但我們如果在Servlet里用了實例變量,那么就變成有狀態了,是非線程安全的。Out,Request,Response,Session,Config,Page,PageContext是線程安全的,Application在整個系統內被使用,所以不是線程安全的.
(2).Struts1也是基於單例模式實現,也就是只有一個Action實例供多線程使用。默認的模式是前台頁面數據通過actionForm傳入,在action中的excute方法接收,這樣action是無狀態的,所以一般情況下Strunts1是線程安全的。如果Action中用了實例變量,那么就變成有狀態了,同樣是非線程安全的。
(3).Struts2默認的實現是Prototype模式。也就是每個請求都新生成一個Action實例,所以不存在線程安全問題。需要注意的是,如果由Spring管理action的生命周期, scope要配成prototype作用域。
(4).如何解決Servlet和Struts1的線程安全問題,當我們能比較好的理解有狀態和無狀態的原理,自然很容易得出結論:不要使用有狀態的bean,也就是不要用實例變量。如果用,就要用prototype模式
5.總結:
Stateless無狀態用單例Singleton模式,Stateful有狀態就用原型Prototype模式。
Stateful 有狀態是多線程編碼的天敵,所以在開發中盡量用Stateless無狀態,無狀態是不變(immutable)模式的應用,有很多優點:不用管線程和同步的問題,如果值是不可變的,程序不用擔心多個線程改變共享狀態,所以可以避免線程競爭的bugs. 因為沒有競爭,就不用用locks等機制,所以無狀態的不變機制,也可以避免產生死鎖現象。
