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
從以上結果可以看出:
第一:在多線程下,使用傳統技術實例化類,根本不存在性能問題;
第二:在多線程下,使用單例模式實例化類,有比較嚴重的性能問題;