單例模式與高並發


SpringMVC與struts2最大區別:SpringMVC使用單例、struts2使用原型(有可能struts2中對象使用后不銷毀而只進行初始化變量再使用)
當某個單例對象中含有不具有並發性的對象(即並發會出錯),為提高並發有三種方法:
1、線程綁定(只允許當前線程使用綁定對象)
2、創建對象池
3、加鎖

單例與原型

單例在並發中可以有多個單例實例化對象。單例模式是只創建一個對象

單例:每個線程都需要使用實例化一個對象,但是對象的獲取方式是不存在創建,存在直接使用。不安全是指一個線程修改了某個單例對象變量,而該對象不會銷毀,會被其他線程使用從而造成該對象變量數據錯誤。
原型:每個線程直接創建自己使用的對象,使用完直接銷毀。
單例是實例化不銷毀被重復使用,原型使用后就銷毀。所以避免單例對象使用中進行修改自身變量。

 


在單例對象中進行線程綁定對象,定義如下:

    private ThreadLocal<Digester> tl = new ThreadLocal<Digester>();
    public Digester getDigester() {
        Digester digester = (Digester) this.tl.get();
        if (null == digester) {
            digester = super.getDigester();
            this.tl.set(digester);
        }
        return digester;
    }

 

在單例對象使用時進行線程綁定一個對象,高並發時單例對象被大量創建,但每個單例只綁定了一個不支持並發的對象。


而在原型中高並下使用單例模式目的只創建一個對象:

publci class Singleton{
     private static Singleton instance = null;
     private Singleton(){}

     public static Singleton getInstance(){
            if(instance == null){
                   instance = new Singleton();
            }
            return instance;
    }
}

 


高並發下會創建多個對象,而目的是只要一個實例對象,所以需要加鎖進行同步

publci class Singleton{
     private static Singleton instance = null;
     private Singleton(){}

     public static synchronized Singleton getInstance(){
            if(instance == null){
                   instance = new Singleton();
            }
            return instance;
    }
} 

 


上面方式很影響性能,所以采用下面方式:

publci class Singleton{
     private static Singleton instance = null;
     private Singleton(){}

     public static Singleton getInstance(){
            if(instance == null){
                   synchronized(Singleton.class){
                        if(instance == null)
                        instance = new Singleton();
                   }           
             }
            return instance;
    }
} 

 



做了單例模式在多線程條件下的性能測試,結果表明我的想法是正確的:試圖用單例來換取性能是不可行的,並發量較小(一般小於200),單例沒有任何性能優勢,也就沒有使用必要,並發量較大(超過500),單例會引起類資源的爭用,實例化速度急劇降低。這個測試說明:weblogic的最大線程=EJB實例的最大實例數=EJB中成員類(也就是業務類)的最大實例數,這幾個東西是一條線下來的,是有內在關系的。
 
測試結果數據:
    一 使用單例模式:
      並發數量:    需要EJB實例數量   需要業務類實例數量  業務類實例化時間平均毫秒數
        200               28               28                         1
        500               33               33                         51
    二 使用傳統技術:
      並發數量:    需要EJB實例數量   需要業務類實例數量  業務類實例化時間平均毫秒數
        200               28               28                          1
        500               33               33                          1                 
    從以上結果可以看出:
    第一:在多線程下,使用傳統技術實例化類,根本不存在性能問題;
    第二:在多線程下,使用單例模式實例化類,有比較嚴重的性能問題;


免責聲明!

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



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