有狀態和無狀態的對象區別


每次的總結,都是一種進步,把自己理解的東西記錄下來不容易,讓別人看懂更不容易。

第一:基本概念:

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都是有狀態信息的。

Java代碼加深影響  :
  1. /** 
  2.  * 非線程安全的Servlet。 
  3.  * @author Peter Wei 
  4.  * 
  5.  */  
  6. public class UnSafeServlet HttpServlet{  
  7.       
  8.     User user;  
  9.     PrintWriter out;  
  10.       
  11.     public void doGet (HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{  
  12.         //do something...  
  13.     }  
  14. }  


Out,Request,Response,Session,Config,Page,PageContext是線程安全的,Application在整個系統內被使用,所以不是線程安全的.

 

 第五:SpringMvc默認是單例默認,Struts2默認的實現是Prototype模式。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM