單例模式:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
解決的問題:一個全局使用的類,頻繁的創建和銷燬。
1. 餓漢式單例(立即加載)
// 餓漢式單例
public class Singleton1 {
// 私有構造
private Singleton1() {}
private static Singleton1 single = new Singleton1();
// 靜態工廠方法
public static Singleton1 getInstance() {
return single;
}
}
2. 懶漢式單例(延時加載)
// 懶漢式單例
public class Singleton2 {
// 私有構造
private Singleton2() {}
private static Singleton2 single = null;
public static Singleton2 getInstance() {
if(single == null){
single = new Singleton2();
}
return single;
}
}
餓漢式和懶漢式的區別:
餓漢式是一加載就把單例實例化,而懶漢式是當調用靜態方法getInstance的時候,初始化單例。
餓漢式是線程安全的,懶漢線程不安全。
懶漢式改進:
方法加鎖或者同步代碼塊加鎖,保證了線程安全,但效率低。每次都要加鎖解鎖。代碼入下
public class Singleton3 {
// 私有構造
private Singleton3() {}
private static Singleton3 single = null;
public static Singleton3 getInstance() {
// 等同於 synchronized public static Singleton3 getInstance()
synchronized(Singleton3.class){
// 注意:裏面的判斷是一定要加的,否則出現線程安全問題
if(single == null){
single = new Singleton3();
}
}
return single;
}
}
繼續改進:
雙重鎖定方法。 先進行判斷,若未被創建時,加鎖。代碼入下
public class Singleton4 {
// 私有構造
private Singleton4() {}
private static Singleton4 single = null;
// 雙重檢查
public static Singleton4 getInstance() {
if (single == null) {
synchronized (Singleton4.class) {
if (single == null) {
single = new Singleton4();
}
}
}
return single;
}
}
當然 ,還可以使用靜態內部類,靜態代碼塊,內部枚舉類等方式