1.餓漢式
public class SingletonInstance { //私有構造方法 private static SingletonInstance (){ } //聲明成員變量 private static SingletonInstance singletonInstance = new SingletonInstance(); //對外提供接口獲取該實例 public static SingletonInstance getSingletonInstance(){ return singletonInstance ; } }
2.懶漢式
public class SingletonInstance { //私有構造方法 private SingletonInstance (){ } //聲明成員變量 private static SingletonInstance singletonInstance ; //對外提供接口獲取該實例 public static SingletonInstance getSingletonInstance(){ if(singletonInstance == null){ singletonInstance = new SingletonInstance(); } return singletonInstance ; } }
餓漢式 懶漢式是經典的單例寫法,但是線程不安全,當然,為保證線程安全,可以對getSingletonInstance()函數加鎖,如下:
public static synchronized SingletonInstance getSingletonInstance(){ return singletonInstance = new SingletonInstance(); }
但是這樣每次獲取單例都會判斷鎖,會很消耗資源,所以餓漢式和懶漢式不推薦使用,推薦使用以下方式
3.double check lock(dcl)
public class SingletonInstance { //私有構造方法 private SingletonInstance (){ } //聲明成員變量 private static SingletonInstance singletonInstance ; //對外提供接口獲取該實例 public static SingletonInstance getSingletonInstance(){ if(singletonInstance == null){ synchronized (SingletonInstance.class){ //兩次判斷是否為null if(singletonInstance==null){ singletonInstance = new SingletonInstance(); } } } return singletonInstance ; } }
DCl 資源利用率高,執行效率也高,缺點是第一次加載的時候會比較慢,而且在高並發的時候,有可能會導致單例不成功(概率很小),推薦使用這種方式
4.靜態內部類
public class SingletonInstance { //私有構造方法 private SingletonInstance (){ } private static class Builder{ //聲明成員變量 private static SingletonInstance singletonInstance = new SingletonInstance(); } //對外提供接口獲取該實例 public static SingletonInstance getSingletonInstance(){ return Builder.singletonInstance ; } }
這種方法,實例只會被創建一次,而且只有在被引用的時候創建,線程安全也能保證,所以推薦使用這種方式
5.以上四種方法,不管哪種方法,在反序列化的時候,都不能保證單例。但是使用枚舉可以避免這個問題,枚舉默認就是線程安全的
public enum Singleton { //enum枚舉類 INSTANCE; }
但是枚舉在android中是不建議使用的,因為枚舉比constants消耗更大的內存,
6.單例管理類創建單例
public class SingletonManager { private static Map<String, Object> objMap = new HashMap<String,Object>();//使用HashMap作為緩存容器 private Singleton() { } public static void registerService(String key, Objectinstance) { if (!objMap.containsKey(key) ) { objMap.put(key, instance) ;//第一次是存入Map } } public static ObjectgetService(String key) { return objMap.get(key) ;//返回與key相對應的對象 } }
7.反序列化杜絕生成新的實例,需要加入以下這個函數
private Object readResolve() throws ObjectStreamException{ return INSTANCE; }