1.餓漢模式
public class Singleton1 {
private static Singleton1 instance = new Singleton1();
private Singleton1() {
}
public static Singleton1 getInstance() {
return instance;
}
/**
* 餓漢模式,線程安全,但是不能延時加載,如果資源不被調用,那麼就會浪費
*/
}
2.懶漢式
public class Singleton2 {
private static Singleton2 instance;
private Singleton2() {
}
public static Singleton2 getInstance() {
if (instance != null) {
instance = new Singleton2();
}
return instance;
}
/**
* 懶漢式,線程安全,可以延時加載,但是不能解決編譯器優化導緻的執行個體未初始化問題
*/
}
3.雙重鎖判斷
public class Singleton3 {
private static Singleton3 instance;
private Singleton3() {
}
public static Singleton3 getInstance() {
if (instance != null) {
synchronized (Singleton3.class) {
if (instance != null) {
instance = new Singleton3();
}
}
}
return instance;
}
/**
* 雙重鎖判斷,JVM優化導緻new操作的三個步驟(如下所示)可能會亂序,
* 進而在并發場景下拿到未初始化的執行個體
*
* 1.配置設定一塊記憶體M
* 2.在M上初始化Singleton3對象
* 3.将M的位址估值給instance變量
*
* JVM可能會讓2和3交換順序,這樣就導緻了未初始化
*/
}
4.靜态内部類
public class Singleton4 {
private Singleton4() {
}
private static class Singleton4InstanceClass {
private static final Singleton4 instance = new Singleton4();
}
public static Singleton4 getInstance() {
return Singleton4InstanceClass.instance;
}
/**
* 采用靜态内部類的形式就相當于是餓漢模式的改進,将不能延時加載的缺點處理掉了,
* 是以該模式線程安全,調用效率高,可以延時加載
*/
}
5.使用
- 單例對象 占用資源少,不需要延時加載,餓漢
- 單例對象 占用資源多,需要延時加載,靜态内部類 好于 懶漢式