Spring單例與執行緒安全小結

2021-07-04 01:07:00 字數 2354 閱讀 8874

一、spring單例模式與執行緒安全

spring框架裡的bean,或者說元件,獲取例項的時候都是預設的單例模式,這是在多執行緒開發的時候要尤其注意的地方。

二、執行緒安全案例:

******dateformat(下面簡稱sdf)類內部有乙個calendar物件引用,它用來儲存和這個sdf相關的日期資訊,例如sdf.parse(datestr), sdf.format(date) 諸如此類的方法引數傳入的日期相關string, date等等, 都是交友calendar引用來儲存的.這樣就會導致乙個問題,如果你的sdf是個static的, 那麼多個thread 之間就會共享這個sdf, 同時也是共享這個calendar引用, 並且, 觀察 sdf.parse() 方法,你會發現有如下的呼叫:

date parse()
這裡會導致的問題就是, 如果 執行緒a 呼叫了 sdf.parse(), 並且進行了 calendar.clear()後還未執行calendar.gettime()的時候,執行緒b又呼叫了sdf.parse(), 這時候執行緒b也執行了sdf.clear()方法, 這樣就導致執行緒a的的calendar資料被清空了(實際上a,b的同時被清空了). 又或者當 a 執行了calendar.clear() 後被掛起, 這時候b 開始呼叫sdf.parse()並順利i結束, 這樣 a 的 calendar內儲存的的date 變成了後來b設定的calendar的date

這個問題背後隱藏著乙個更為重要的問題–無狀態:無狀態方法的好處之一,就是它在各種環境下,都可以安全的呼叫。衡量乙個方法是否是有狀態的,就看它是否改動了其它的東西,比如全域性變數,比如例項的字段。format方法在執行過程中改動了******dateformat的calendar欄位,所以,它是有狀態的。

這也同時提醒我們在開發和設計系統的時候注意下一下三點:

1.自己寫公用類的時候,要對多執行緒呼叫情況下的後果在注釋裡進行明確說明

2.對執行緒環境下,對每乙個共享的可變變數都要注意其執行緒安全性

3.我們的類和方法在做設計的時候,要盡量設計成無狀態的

三.解決辦法

1.需要的時候建立新例項:

說明:在需要用到******dateformat 的地方新建乙個例項,不管什麼時候,將有執行緒安全問題的物件由共享變為區域性私有都能避免多執行緒問題,不過也加重了建立物件的負擔。在一般情況下,這樣其實對效能影響比不是很明顯的。

2.使用同步:同步******dateformat物件

public

class

datesyncutil

}public

static date parse(string strdate) throws parseexception

} }

說明:當執行緒較多時,當乙個執行緒呼叫該方法時,其他想要呼叫此方法的執行緒就要block,多執行緒併發量大的時候會對效能有一定的影響。

3.使用threadlocal: 

public

class concurrentdateutil

};public

static date parse(string datestr) throws parseexception

public

static string format(date date) }或

public

class threadlocaldateutil

return df;

} public

static string formatdate(date date) throws parseexception

public

static date parse(string strdate) throws parseexception

}

說明:使用threadlocal, 也是將共享變數變為獨享,執行緒獨享肯定能比方法獨享在併發環境中能減少不少建立物件的開銷。如果對效能要求比較高的情況下,一般推薦使用這種方法。

4.拋棄jdk,使用其他類庫中的時間格式化類:

1.使用apache commons 裡的fastdateformat,宣稱是既快又執行緒安全的******dateformat, 可惜它只能對日期進行format, 不能對日期串進行解析。

2.使用joda-time類庫來處理時間相關問題

做乙個簡單的壓力測試,方法一最慢,方法三最快,但是就算是最慢的方法一效能也不差,一般系統方法一和方法二就可以滿足,所以說在這個點很難成為你系統的瓶頸所在。從簡單的角度來說,建議使用方法一或者方法二,如果在必要的時候,追求那麼一點效能提公升的話,可以考慮用方法三,用threadlocal做快取。

joda-time類庫對時間處理方式比較完美,建議使用。

單例問題與執行緒安全

沒有執行緒安全性問題 public class singletondemo2 public static singletondemo2 getinstance return instance 如果遇到多執行緒。上面的 會返回不同的 singletondemo2 例項。違背了單例設計。需要加上 syn...

單例模式與執行緒安全

請看如下的單例類 class singleton return singleton 首先判斷singleton是否為null,如果是就建立singleton物件,否則直接返回singleton。但是判斷和建立並非原子操作,假設執行緒1正在執行null singleton,判斷為true,準備執行下一...

單例模式與執行緒安全

在類載入的時候,就已經進行例項化,無論之後用不用到。如果該模擬較佔記憶體,之後又沒用到,就白白浪費了資源。public class hungersingleton private hungersingleton public static void main string args start 在需...