三部曲:java
(1)私有化構造方法 (2)私有化靜態本類對象做爲屬性 (3)提供公有靜態方法獲取本類對象
1.普通的餓漢式(靜態的內部)安全
public class Client { public static void main(String[] args) { Singleton.getInstance(); } static class Singleton { private static final Singleton instance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return instance; } } }
2.餓漢式靜態代碼塊單例模式併發
//餓漢式靜態代碼塊單例模式 public class HungryStaticSingleton { private static final HungryStaticSingleton instance; static { instance = new HungryStaticSingleton(); } private HungryStaticSingleton(){} public static HungryStaticSingleton getInstance(){ return instance; } }
3.餓漢式靜態代碼塊單例模式ide
/** * 優勢:執行效率高,性能高,沒有任何的鎖 * 缺點:某些狀況下,可能會形成內存浪費 */ //餓漢式靜態代碼塊單例模式 public class HungrySingleton { private static final HungrySingleton instance = new HungrySingleton(); private HungrySingleton(){} public static HungrySingleton getInstance(){ return instance; } }
1.懶漢式單例模式在外部須要使用的時候才進行實例化,這種是線程不安全的,若是多個線程同時併發訪問,假設多個線程同時都進入到了 if(instance == null){}條件判斷裏面,那麼就會同時建立多個對象。性能
/** * 優勢:節省了內存,線程安全 * 缺點:性能低 */ //懶漢式單例模式在外部須要使用的時候才進行實例化 public class LazySimpleSingletion { //靜態塊,公共內存區域 private static LazySimpleSingletion instance; private LazySimpleSingletion(){} public synchronized static LazySimpleSingletion getInstance(){ if(instance == null){ instance = new LazySimpleSingletion(); } return instance; } }
2.單次檢查機制(使用類鎖),這種也是有缺點的,使用的 synchronized 關鍵字,嚴重的影響了性能.this
public class Singleton { private static Singleton instance = null; public static Singleton getInstance() { synchronized (Singleton.class) { if(null == instance) { instance = new Singleton(); } } return instance; } }
3.利用雙重檢查機制(DCL) ,保證了線程的安全spa
/** * 優勢:性能高了,線程安全了 * 缺點:可讀性難度加大,不夠優雅 */ public class LazyDoubleCheckSingleton { private volatile static LazyDoubleCheckSingleton instance; private LazyDoubleCheckSingleton(){} public static LazyDoubleCheckSingleton getInstance(){ //檢查是否要阻塞 if (instance == null) { synchronized (LazyDoubleCheckSingleton.class) { //檢查是否要從新建立實例 if (instance == null) { instance = new LazyDoubleCheckSingleton(); //指令重排序的問題 } } } return instance; } }
4.自認爲史上最牛的單例模式的實現方式 (這裏有個技術上的高深的點技術基礎點,說到底仍是技術的基礎和本質)----->>>> 利用了Java自己語法特色,內部類默認不加載線程
/* ClassPath : LazyStaticInnerClassSingleton.class LazyStaticInnerClassSingleton$LazyHolder.class 優勢:寫法優雅,利用了Java自己語法特色,性能高,避免了內存浪費,不能被反射破壞 缺點:不優雅 */ //這種形式兼顧餓漢式單例模式的內存浪費問題和synchronized的性能問題 //完美地屏蔽了這兩個缺點 //自認爲史上最牛的單例模式的實現方式 public class LazyStaticInnerClassSingleton { //使用LazyInnerClassGeneral的時候,默認會先初始化內部類 //若是沒使用,則內部類是不加載的 private LazyStaticInnerClassSingleton(){ if(LazyHolder.INSTANCE != null){ throw new RuntimeException("不容許建立多個實例"); } } //每個關鍵字都不是多餘的,static是爲了使單例的空間共享,保證這個方法不會被重寫、重載 private static LazyStaticInnerClassSingleton getInstance(){ //在返回結果之前,必定會先加載內部類 return LazyHolder.INSTANCE; } //利用了Java自己語法特色,內部類默認不加載 private static class LazyHolder{ private static final LazyStaticInnerClassSingleton INSTANCE = new LazyStaticInnerClassSingleton(); } }
5.枚舉法code
public enum EnumSingleton { INSTANCE; private Object data; public Object getData() { return data; } public void setData(Object data) { this.data = data; } public static EnumSingleton getInstance(){return INSTANCE;} }
6.序列化一個單列對象對象
import java.io.Serializable; public class SeriableSingleton implements Serializable { //序列化 //把內存中對象的狀態轉換爲字節碼的形式 //把字節碼經過IO輸出流,寫到磁盤上 //永久保存下來,持久化 //反序列化 //將持久化的字節碼內容,經過IO輸入流讀到內存中來 //轉化成一個Java對象 public final static SeriableSingleton INSTANCE = new SeriableSingleton(); private SeriableSingleton(){} public static SeriableSingleton getInstance(){ return INSTANCE; } private Object readResolve(){ return INSTANCE;} }
7.手動建立一個單列對象(根據類名來建立)
public class ContainerSingleton { private ContainerSingleton(){} private static Map<String,Object> ioc = new ConcurrentHashMap<String, Object>(); public static Object getInstance(String className){ Object instance = null; if(!ioc.containsKey(className)){ try { instance = Class.forName(className).newInstance(); ioc.put(className, instance); }catch (Exception e){ e.printStackTrace(); } return instance; }else{ return ioc.get(className); } } }
8.ThreadLocal設置單列
public class ThreadLocalSingleton { private static final ThreadLocal<ThreadLocalSingleton> threadLocaLInstance = new ThreadLocal<ThreadLocalSingleton>(){ @Override protected ThreadLocalSingleton initialValue() { return new ThreadLocalSingleton(); } }; private ThreadLocalSingleton(){} public static ThreadLocalSingleton getInstance(){ return threadLocaLInstance.get(); } }