設計模式:解決一些固定場景的固定套路,是一種代碼風格的知道指南。設計模式不止23種
1、單例設計模式
單例設計模式:確保一個類只有一個實例,提供全局訪問點
單例模式的實現方式:
1:餓漢模式
/*** 餓漢模式*/
class SingletonPattern {private static SingletonPattern instance = new SingletonPattern();private SingletonPattern () {// 設置為private,外部類就不能通過new創建實例}public static SingletonPattern getInstance() {return instance;}
}public class SinglePattern {public static void main(String[] args) {SingletonPattern instance1 = SingletonPattern.getInstance();SingletonPattern instance2 = SingletonPattern.getInstance();System.out.println(instance1 == instance2); // true}
}
2:懶漢模式
懶漢模式(線程不安全)
此處的代碼是存在線程安全問題的。
1:原子性
應該將此處代碼打包成原子的,不讓代碼穿插操作。所以就對代碼進行加鎖,解決原子性問題
if(instance == null) {
? ? ? ? ? ? instance = new SingleLazy();
? ? ? ? }
2:指令重排序
instance = new SingleLazy(); 此處這個new操作實際有好幾步指令,粗略分為下面三步
1:內存分配
2:初始化零值
3:執行構造函數
實際的執行順序是1-》2-》3,但是編譯器優化的指令重排序,可能會將原本執行順序重排為1-》3-》2,所以為了避免指令重排序,需要在instance上加上volatile
class SingleLazy {/*** 單例模式* 懶漢模式:創建實例的時機比較晚,不是那么急迫*/private static SingleLazy instance = null;private SingleLazy() {}// 第一次使用實例的時候,才創建實例public static SingleLazy getInstance() {if(instance == null) {// return new SingleLazy(); // 這樣寫是錯的,這樣每次get都會newinstance = new SingleLazy();}return instance;}
}
public class SingleLazyPattern {public static void main(String[] args) {SingleLazy instance1 = SingleLazy.getInstance();SingleLazy instance2 = SingleLazy.getInstance();System.out.println(instance1 == instance2); // true}
}
?懶漢模式(線程安全)
又在鎖的外面加了一條判斷,目的就是只在第一次調用getInstance方法是進行加鎖,避免重復加鎖
if(instance == null)?
// 如果不進行判斷,那么每次調用getInstance方法都會進行加鎖操作
// 但是如果加了判斷,只會在第一次調用getInstance方法進行加鎖操作
?
class SinglePattern {private static volatile SinglePattern instance = null; // volatile解決指令重排序問題private static Object lock = new Object();private SinglePattern() {// 避免外部創建實例}public static SinglePattern getInstance() {if(instance == null) {// 如果不進行判斷,那么每次調用getInstance方法都會進行加鎖操作// 但是如果加了判斷,只會在第一次調用getInstance方法進行加鎖操作synchronized(lock) { // 加鎖,解決原子性問題if(instance == null) {instance = new SinglePattern();}}}return instance;}
}public class SingleLazyPattern {public static void main(String[] args) {SinglePattern instance1 = SinglePattern.getInstance();SinglePattern instance2 = SinglePattern.getInstance();System.out.println(instance1 == instance2);}}