1、定義
確保某個類只有一個實例,而且自行實例化并向整個系統(tǒng)提供這個實例
2、特點
- 單例類只能有一個實例。
- 單例類必須自己創(chuàng)建自己的唯一實例。
- 單例類必須給所有其他對象提供這一實例。
3、單例模式可以分為懶漢式和餓漢式
- 懶漢式單例模式:在類加載時不初始化。
- 餓漢式單例模式:在類加載時就完成了初始化,所以類加載比較慢,但獲取對象的速度快。
1)懶漢式,線程不安全
這種方式是最基本的實現(xiàn)方式,這種實現(xiàn)最大的問題就是不支持多線程。因為沒有加鎖 synchronized,所以嚴格意義上它并不算單例模式。
public class SingletonDemo1 {
private static SingletonDemo1 instance;
private SingletonDemo1(){}
public static SingletonDemo1 getInstance(){
if (instance == null) {
instance = new SingletonDemo1();
}
return instance;
}
}
2)懶漢式,線程安全
- 優(yōu)點:第一次調(diào)用才初始化,避免內(nèi)存浪費。
- 缺點:必須加鎖 synchronized 才能保證單例,但加鎖會影響效率。
public class SingletonDemo2 {
private static SingletonDemo2 instance;
private SingletonDemo2(){}
public static synchronized SingletonDemo2 getInstance(){
if (instance == null) {
instance = new SingletonDemo2();
}
return instance;
}
}
3)餓漢式
基于classloder機制避免了多線程的同步問題,不過,instance在類裝載時就實例化,這時候初始化instance沒有達到lazy loading的效果。
- 優(yōu)點:沒有加鎖,執(zhí)行效率會提高。
- 缺點:類加載時就初始化,浪費內(nèi)存。
public class SingletonDemo3 {
private static SingletonDemo3 instance = new SingletonDemo3();
private SingletonDemo3(){}
public static SingletonDemo3 getInstance(){
return instance;
}
}
4)餓漢,變種
在類初始化即實例化instance
public class SingletonDemo4 {
private static SingletonDemo4 instance = null;
static{
instance = new SingletonDemo4();
}
private SingletonDemo4(){}
public static SingletonDemo4 getInstance(){
return instance;
}
}
5)登記式/靜態(tài)內(nèi)部類
這種方式能達到雙檢鎖方式一樣的功效,但實現(xiàn)更簡單。對靜態(tài)域使用延遲初始化,應(yīng)使用這種方式而不是雙檢鎖方式。這種方式只適用于靜態(tài)域的情況,雙檢鎖方式可在實例域需要延遲初始化時使用。
- 利用了classloder的機制來保證初始化instance時只有一個線程.
- 這種方式是SingletonDemo5 類被裝載了,instance不一定被初始化。因為SingletonHolder類沒有被主動使用,只有顯示通過調(diào)用getInstance方法時,才會顯示裝載SingletonHolder類,從而實例化instance.
public class SingletonDemo5 {
private static class SingletonHolder{
private static final SingletonDemo5 instance = new SingletonDemo5();
}
private SingletonDemo5(){}
public static final SingletonDemo5 getInsatance(){
return SingletonHolder.instance;
}
}
6)枚舉
自動支持序列化機制,絕對防止多次實例化。
public enum SingletonDemo6 {
instance;
public void whateverMethod(){
}
}
7)雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking)
這種方式采用雙鎖機制,安全且在多線程情況下能保持高性能
public class SingletonDemo7 {
private volatile static SingletonDemo7 singletonDemo7;
private SingletonDemo7(){}
public static SingletonDemo7 getSingletonDemo7(){
if (singletonDemo7 == null) {
synchronized (SingletonDemo7.class) {
if (singletonDemo7 == null) {
singletonDemo7 = new SingletonDemo7();
}
}
}
return singletonDemo7;
}
}