一 概念
這種模式涉及到一個單一的類,該類負責創(chuàng)建自己的對象,同時確保只有單個對象被創(chuàng)建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象
- 單例類只能有一個實例
- 單例類必須自己創(chuàng)建自己的唯一實例
- 單例類必須給所有其他對象提供這一實例
關鍵點:
- 構造函數(shù)為私有的
- getIntence()方法中需要使用同步鎖synchronized防止多線程同時進入造成instance被多次實例化
- 使用場景:參考單例模式|菜鳥教程
二 單例模式的幾種實現(xiàn)方式
1.懶漢式,線程不安全
是否Lazy初始化:是
是否多線程安全:否
缺點:lazy loading很明顯,線程不安全,多線程下無法正常工作
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2.懶漢式,線程安全
是否 Lazy 初始化:是
是否多線程安全:是
優(yōu)點:第一次調(diào)用才初始化,避免內(nèi)存浪費。
缺點:必須加鎖 synchronized 才能保證單例,但加鎖會影響效率。
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3.餓漢式
是否 Lazy 初始化:否
是否多線程安全:是
實現(xiàn)難度:易
描述:這種方式比較常用,但容易產(chǎn)生垃圾對象。
優(yōu)點:沒有加鎖,執(zhí)行效率會提高。
缺點:類加載時就初始化,浪費內(nèi)存。
它基于 classloder 機制避免了多線程的同步問題,不過,instance 在類裝載時就實例化,雖然導致類裝載的原因有很多種,在單例模式中大多數(shù)都是調(diào)用 getInstance 方法, 但是也不能確定有其他的方式(或者其他的靜態(tài)方法)導致類裝載,這時候初始化 instance 顯然沒有達到 lazy loading 的效果。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
4.雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking)
是否 Lazy 初始化:是
是否多線程安全:是
實現(xiàn)難度:較復雜
描述:這種方式采用雙鎖機制,安全且在多線程情況下能保持高性能。
getInstance() 的性能對應用程序很關鍵。
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
public void say(){
System.out.println("hello word");
}
}
調(diào)用:
public static void main(String[] args) {
Singleton singleton = Singleton.getSingleton();
singleton.say();
}
運行結果:
hello word