天天看點

有狀态(Stateful)與無狀态(Stateless)

有狀态(Stateful)與無狀态(Stateless)

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等機制,是以無狀态的不變機制,也可以避免産生死鎖現象。 

繼續閱讀