參考連接:html
http://www.runoob.com/design-pattern/singleton-pattern.htmljava
一個類只有一個實例,每次都返回相同實例安全
須要控制實例數目時可選擇使用該模式,建議使用靜態內部類實現,只有在調用getInstance時才實例化,實現了Lazy初始化,也是多線程安全。利用classloader機制保證初始化instance時只有一個線程。多線程
單俐對象每每存在於DAO層,例如SessionFactory函數
在內存中只有一個實例,減小內存開銷。spa
/** * Created by liang on 2018/5/8. */ public class SingletonDemo { private static SingletonDemo instance; // 構造函數私有化 private SingletonDemo() {} public static SingletonDemo getInstance() { if (instance == null) { instance = new SingletonDemo(); } return instance; } }
/** * 線程安全的單俐模式實現 * Created by liang on 2018/5/8. */ public class ThreadSafeSingletonDemo { private static ThreadSafeSingletonDemo instance; private ThreadSafeSingletonDemo() {} public static synchronized ThreadSafeSingletonDemo getInstance() { if (instance == null) { instance = new ThreadSafeSingletonDemo(); } return instance; } }
/** * 使用靜態內部類 * 在調用getInstance()時才加載該單俐類,這種方法也是線程安全的 * Created by liang on 2018/5/8. */ public class StaticInnerClassSingletonDemo { private static class SingletonHolder { private static StaticInnerClassSingletonDemo instance = new StaticInnerClassSingletonDemo(); } private StaticInnerClassSingletonDemo() {} public static StaticInnerClassSingletonDemo getInstance() { return SingletonHolder.instance; } }
/** * 雙重鎖校驗 * Step 1: 線程A訪問getInstance()方法,由於單俐尚未實例化,因此進入了鎖定塊 * Step 2: 線程B訪問getInstance()方法,得以訪問接下來的代碼塊,而接下來代碼塊已經被線程A鎖定 * Step 3: 線程A進入下一判斷,由於單俐尚未實例化,因此進行單俐實例化,成功實例化後退出代碼塊,解除鎖定 * Step 4: 線程B進入接下來的代碼塊,鎖定線程,進入下一判斷,由於已經實例化,退出代碼塊,解除鎖定。 * Step 5: 線程A獲取到了單俐實例並返回,線程B沒有獲取到單俐返回Null * Created by liang on 2018/5/8. */ public class DoubleValidateSingletonDemo { // 每次都返回最新的值 private volatile static DoubleValidateSingletonDemo instance; private DoubleValidateSingletonDemo() {} public static DoubleValidateSingletonDemo getInstance() { if (instance == null) { synchronized (DoubleValidateSingletonDemo.class) { if (instance == null) { instance = new DoubleValidateSingletonDemo(); } } } return instance; } }