一.什麼是單例以及單例的使用場景就很少說了,不清楚的能夠看我上篇文章或者自行查找安全
二.單例和多併發之間的規則併發
單例就是隻能建立一個實例對象,而多併發狀況下若是不處理一下單例的寫法很難保證只建立一個實例對象,因此後面會出問題jvm
處理的思路:在建立對象的時候使用同步鎖,或者直接懶人作法---放一個靜態的實例對象函數
三.幾種常見的單例模式的寫法spa
1.最常規的(線程不安全--不支持多併發)線程
public class Singleton { //一個靜態的實例 private static Singleton singleton; //私有化構造函數 private Singleton(){} //給出一個公共的靜態方法返回一個單一實例 public static Singleton getInstance(){ if (singleton == null) { singleton = new Singleton(); } return singleton; }
2.上面的經常使用的是不支持併發的,因此後面考慮在方法上加同步鎖,可是若是在上面那個獲取對象的方法上加鎖則會每次在獲取對象時都須要等待,蠻費時間的,因此不能這麼玩,code
可使用以下方法內部類寫法(其實我感受他和餓漢式差很少,都是new一個靜態實例放在那裏)對象
public class Singleton { /* 私有構造方法,防止被實例化 */ private Singleton() { } /* 此處使用一個內部類來維護單例 */ private static class SingletonFactory { private static Singleton instance = new Singleton(); } /* 獲取實例 */ public static Singleton getInstance() { return SingletonFactory.instance; } } 備註: 第一次調用getInstance的時候,JVM可以幫咱們保證instance只被建立一次,而且會保證把賦值給instance的內存初始化完畢,由於JVM內部的機制可以保證當一個類被加載的時候,這個類的加載過程是線程互斥的 能夠對比一下餓漢式寫法: public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; } }
3.或者在建立類的那個時刻同步就行,獲取對象的方法就不一樣步(和懶漢式相似,須要時加載就行)blog
public class SingletonTest { private static SingletonTest instance = null; private SingletonTest() { } private static synchronized void syncInit() { if (instance == null) { instance = new SingletonTest(); } } public static SingletonTest getInstance() { if (instance == null) { syncInit(); } return instance; } } 懶漢式的不高效寫法,至關於也是同步了獲取對象的方法 public class Singleton { private static Singleton instance; private Singleton(){} public static synchronized Singleton getInstance(){ if (instance == null) { instance = new Singleton(); } return instance; } }
4.所謂的雙重鎖寫法(至關於變相的在類的建立時加同步鎖,和方法三原理相似或者和方法二內部類利用jvm類加載機制相似)內存
public class Singleton{ private volatile static Singleton singleton; private Singleton(){} public static Singleton getSingleton(){ if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }