目錄
單例模式7種實現及利弊分析
單例模式三要素
- 私有的構造方法;
- 指向自己實例的私有靜態引用;
- 以自己實例為返回值的靜態的公有方法
1.餓漢式
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton(){};
public static Singleton getSingleton(){
return singleton;
}
}
優點:線程安全,在類加載完成時就完成了初始化,調用效率高
缺點:類加載較慢,無法達到懶加載的效果
2.懶漢式(非線程安全)
public class Singleton{
private static Singleton singleton;
private Singleton(){};
public static Singleton getSingleton(){
if(singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
優點:節約資源,實現懶加載
缺點:非線程安全,獲取對象需要實例化,調用效率低
3.懶漢式(synchronized)
public class Singleton{
private static Singleton singleton;
private Singleton(){};
// 1.synchronized塊 實現線程安全
/*public static Singleton getSingleton(){
synchronized(Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
*/
// 2.synchronized方法 實現線程安全
public static synchronized Singleton getSingleton(){
if(singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
優點:線程安全,實現懶加載
缺點:獲取對象需要實例化,調用效率低
4.懶漢式(靜態內部類)
public class Singleton{
private static class Holder{
private static Singleton singleton = new Singleton();
}
private Singleton(){};
public static Singleton getSingleton(){
return Holder.singleton;
}
}
優點:線程安全,實現懶加載
缺點:暫無
5.懶漢式(雙重鎖DCL)
public class Singleton{
//volatile禁止指令重排序,避免DCL失效問題
private static volatile Singleton singleton;
private Singleton(){};
public static Singleton getSingleton(){
//避免重復的同步
if(singleton == null){
//如果未實例化,才進行加鎖
synchronized(Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
優點:線程安全,實現懶加載
缺點:能被反射破解,不是絕對安全
6.懶漢式(ThreadLocal)
public class Singleton {
private static volatile Singleton singleton;
private static ThreadLocal<Singleton> threadLocal = new ThreadLocal<>();
private Singleton(){};
public static void createSingleton(){
synchronized (Singleton.class){
if (singleton == null){
singleton = new Singleton();
}
}
threadLocal.set(singleton);
}
public static Singleton getSingleton(){
if(threadLocal.get() == null){
createSingleton();
}
return singleton;
}
}
優點:也相當於實現了雙重檢查,線程安全
缺點:效率不及傳統雙重檢查
7.枚舉類型(建議使用)
public enum Singleton {
INSTANCE;
public Singleton getSingleton(){
return INSTANCE;
}
}
優點:安全,避免了反射攻擊,編碼簡單
缺點:無法實現懶加載,無法被繼承