總結一波單例設計模式的幾種寫法以及各自存在的優缺點。
1,餓漢式
顧名思義,執行個體對象早早的就建立出來了。這種方式在類加載的時候就完成了初始化,是以類加載過程比較緩慢,但是在使用過程中擷取執行個體對象的速度比較快,也因為這種方式是基于類加載機制的,是以避免了多線程的同步問題。
public class SingleTon {
private static SingleTon instance = new SingleTon();
private SingleTon(){}
public static SingleTon getInstance(){
return instance;
}
}
優點:擷取對象的速度快;避免了多線程的同步問題
缺點:類加載過程慢
2,懶漢式(線程不安全)
顧名思義,執行個體對象建立時間較晚。執行個體對象在使用者第一次調用的時候初始化,雖然節約了資源,但是第一次加載時反應稍慢,而且在多線程的情況下不能正常使用。
public class SingleTon {
private static SingleTon instance;
private SingleTon() {}
public static SingleTon getInstance() {
if (instance == null) {
instance = new SingleTon();
}
return instance;
}
}
優點:節約資源
缺點:第一次加載時需要執行個體化,反應稍慢;多線程下不能正常工作
3,懶漢式(線程安全)
這種寫法時線程安全的,在多線程情況下是可以正常工作的,但是每次擷取執行個體對象的時候都需要進行同步,造成不必要的同步開銷。在移動應用開發端用到同步的情況很少,是以不建議使用。
public class SingleTon {
private static SingleTon instance;
private SingleTon() {}
public static synchronized SingleTon getInstance() {
if (instance == null) {
instance = new SingleTon();
}
return instance;
}
}
優點:在多線程下可以安全的使用
缺點:造成不必要的同步開銷
4,雙重檢查機制(DCL)
這種寫法有兩次判空。第一次判空是減少不必要的同步開銷,也是對上面寫法的改進;第二次判空是建立執行個體對象。注意這裡使用了volatile關鍵字
public class SingleTon {
private static volatile SingleTon instance;
private SingleTon() {}
public static SingleTon getInstance() {
if (instance == null) {
synchronized (SingleTon.class) {
if (instance == null) {
instance = new SingleTon();
}
}
}
return instance;
}
}
優點:資源使用率高,線程安全
缺點:第一次加載時反應稍慢,在高并發環境下有缺陷
5,靜态内部類
這種單例模式在第一次類加載時并不會初始化,隻有在第一次調用getInstance();時虛拟機加載SingletonHolder并初始化SingleTon執行個體,也是線程安全的,也是推薦使用的。
public class SingleTon {
private SingleTon() {}
public static SingleTon getInstance(){
return SingletonHolder.instance;
}
private static class SingletonHolder{
private static final SingleTon instance = new SingleTon();
}
}
優點:線程安全,節約資源
缺點:第一次加載時反應稍慢