單例模式()
當使用SingletoncreateString()執行任務時程序輸出
Singleton is create
createString in Singleton
可以看到雖然此時並沒有使用單例類但它還是被創建出來這也許是開發人員所不願意見到的為了解決這個問題並以此提高系統在相關函數調用時的反應速度就需要引入延遲加載機制
public class LazySingleton {
private LazySingleton(){
Systemoutprintln(LazySingleton is create)
//創建單例的過程可能會比較慢
}
private static LazySingleton instance = null;
public static synchronized LazySingleton getInstance() {
if (instance==null)
instance=new LazySingleton()
return instance;
}
}
首先對於靜態成員變量instance初始值賦予null確保系統啟動時沒有額外的負載其次在getInstance()工廠方法中判斷當前單例是否已經存在若存在則返回不存在則再建立單例這裡尤其還要注意getInstance()方法必須是同步的否則在多線程環境下當線程正新建單例時完成賦值操作前線程可能判斷instance為null故線程也將啟動新建單例的程序而導致多個實例被創建故同步關鍵字是必須的
使用上例中的單例實現雖然實現了延遲加載的功能但和第一種方法相比它引入了同步關鍵字因此在多線程環境中它的時耗要遠遠大於第一種單例模式以下測試代碼就說明了這個問題
@Override
public void run(){
for(int i=;i<;i++)
SingletongetInstance()
//LazySingletongetInstance()
Systemoutprintln(spend:+(SystemcurrentTimeMillis()begintime))
}
開啟個線程同時完成以上代碼的運行使用第種類型的單例耗時ms而使用LazySingleton卻相對耗時約ms性能至少相差個數量級
注意在本書中會使用很多類似的代碼片段用於測試不同代碼的執行速度在不同的計算機上其測試結果很可能與筆者不同讀者大可不必關心測試數據的絕對值只要觀察用於比較的目標代碼間的相對耗時即可
為了使用延遲加載引入的同步關鍵字反而降低了系統性能是不是有點得不償失呢?為了解決這個為問題還需要對其進行改進
public class StaticSingleton {
private StaticSingleton(){
Systemoutprintln(StaticSingleton is create)
}
private static class SingletonHolder {
private static StaticSingleton instance = new StaticSingleton()
}
public static StaticSingleton getInstance() {
return SingletonHolderinstance;
}
}
在這個實現中單例模式使用內部類來維護單例的實例當StaticSingleton被加載時其內部類並不會被初始化故可以確保當StaticSingleton類被載入JVM時不會初始化單例類而當getInstance()方法被調用時才會加載SingletonHolder從而初始化instance同時由於實例的建立是在類加載時完成故天生對多線程友好getInstance()方法也不需要使用同步關鍵字因此這種實現方式同時兼備以上兩種實現的優點
注意使用內部類的方式實現單例既可以做到延遲加載也不必使用同步關鍵字是一種比較完善的實現
返回目錄Java程序性能優化讓你的Java程序更快更穩定
編輯推薦
Java程序設計培訓視頻教程
JEE高級框架實戰培訓視頻教程
JME移動開發實戰教學視頻
Visual C++音頻/視頻技術開發與實戰
Oracle索引技術
ORACLEG數據庫開發優化指南
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27836.html