導語:單例模式應該是使用最爲廣泛的一種模式了,以前也知道懶漢式和惡漢式,但是沒有總結過,這次看到了關於單例模式的基本可能的實現方式,現在記錄一下,方便以後自己可以看。
一.餓漢式
/**
* 餓漢式單例
* Created by 追風車的面癱
*/
public class Singleton {
public static final Singleton sInstance = new Singleton();
public Singleton(){}
public static Singleton getInstance(){
return sInstance;
}
}
特點:節省時間,但類創建之後就實例化了,無論使用與否,始終在內存中,線程始終是安全的。
二.懶漢式
/** * 懶漢式單例
* Created by 追風車的面癱
*/
public class Singleton {
private static Singleton sInstance = null;
public Singleton(){
}
public synchronized static Singleton getsInstance(){
if(sInstance==null){
sInstance = new Singleton();
}
return sInstance;
}
}
特點:節省了空間,在需要的時候才創建,但第一次獲取時會有點慢,線程不安全。
三.雙重檢查鎖定
/**
*
* 雙重檢查鎖定單例
* Created by 追風車的面癱
*/
public class Singleton {
public Singleton(){
}
public static Singleton getsInstance(){
if(sInstance == null){
synchronized (Singleton.class){
if(sInstance == null){
sInstance = new Singleton();
}
}
}
return sInstance;
}
}
特點:既能在需要時初始化,又能夠保證線程安全,且單例對象初始化後調用getInstance()不進行同步鎖。
但是考慮到Java併發過程中,Java編譯器允許處理器亂序執行,有可能會有bug,造成空指針的錯誤,但JDK1.5開始,官方具體化了volatile關鍵字,可以解決這個問題,只需改一句代碼:
//volatile修飾後,更安全
private volatile static Singleton sInstance =null;
關於volatile關鍵字,可查看http://www.cnblogs.com/dolphin0520/p/3920373.html,講的非常清楚。
四.靜態內部類
/**
* 靜態內部類實現單例 推薦
* Created by 追風車的面癱
*/
public class Singleton {
public Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.sInstance;
}
/**
* 靜態內部類
*/
private static class SingletonHolder{
private static final Singleton sInstance = new Singleton();
}
}
特點:線程安全,也保證了對象唯一性。
五.枚舉單例
/** *枚舉單例 *Created by 追風車的面癱 */
public enum Singleton {
INSTANCE;
public void doSomething(){
System.out.println("do sth.");
}
}
特點:寫法簡單,默認線程就是安全的。相比以上幾個方式,有一個優點,即使反序列化也不會重新生成新的實例。
六.使用容器實現單例模式
/**
* Created by 追風車的面癱
*/
public class SingletonManager {
private static Map<String,Object> objMap = new HashMap<String,Object>();
private SingletonManager(){}
public static void registerService(String key,Object instance){
if(!objMap.containsKey(key)){
objMap.put(key,instance);
}
}
public static Object getService(String key){
return objMap.get(key);
}
}
特點:程序初始時,將多種單例類型注入到一個統一的管理類,使用時根據key獲取,可以管理多種單例。比如android源碼中Context的實現類ContextImpl類中就有用到這種方式的單例獲取相關Service。
總結:大部分情況下,推薦使用帶有volatile關鍵字的雙重檢查鎖定和靜態內部類。(希望以後能繼續堅持寫筆記和關於安卓的總結)