天天看點

Java并發程式設計 - 有狀态 & 無狀态的對象差別

一、基本概念

1、有狀态就是有資料存儲功能。有狀态對象(Stateful Bean),就是有執行個體變量的對象,可以儲存資料,是非線程安全的。在不同方法調用間不保留任何狀态。

2、無狀态就是一次操作,不能儲存資料。無狀态對象(Stateless Bean),就是沒有執行個體變量的對象.不能儲存資料,是不變類,是線程安全的。

二、看代碼加深印象

/** 
 * 有狀态bean,有state,user等屬性,并且user有存偖功能,是可變的。 
 *  
 * @author Peter Wei 
 *  
 */ 
public class StatefulBean {  
   
    public int state;  
    // 由于多線程環境下,user是引用對象,是非線程安全的  
    public User user;  
   
    public int getState() {  
        return state;  
    }  
   
    public void setState(int state) {  
        this.state = state;  
    }  
   
    public User getUser() {  
        return user;  
    }  
   
    public void setUser(User user) {  
        this.user = user;  
    }  
}  
   
/** 
 * 無狀态bean,不能存偖資料。因為沒有任何屬性,是以是不可變的。隻有一系統的方法操作。 
 *  
 * @author Peter Wei 
 *  
 */ 
public class StatelessBeanService {  
   
    // 雖然有billDao屬性,但billDao是沒有狀态資訊的,是Stateless Bean.  
    BillDao billDao;  
   
    public BillDao getBillDao() {  
        return billDao;  
    }  
   
    public void setBillDao(BillDao billDao) {  
        this.billDao = billDao;  
    }  
   
    public List<User> findUser(String Id) {  
         return null;  
    }  
}      

三、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作用域。  

四、Servlet是單例模式

1、Servlet體系結構是建立在Java多線程機制之上的,它的生命周期是由Web 容器負責的。一個Servlet類在Application中隻有一個執行個體存在,也就是有多個線程在使用這個執行個體。這是單例模式的應用。無狀态的單例是線程安全的,但我們如果在Servlet裡用了執行個體變量,那麼就變成有狀态了,是非線程安全的。如下面的用法就是不安全的,因為user,out都是有狀态資訊的。

/** 
 * 非線程安全的Servlet。 
 * @author Peter Wei 
 * 
 */  
public class UnSafeServlet HttpServlet{  
      
    User user;  
    PrintWriter out;  
      
    public void doGet (HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{  
        //do something...  
    }  
}      

五、SpringMvc預設是單例預設,Struts2預設的實作是Prototype模式。

繼續閱讀