單列模式就是一個類當中創(chuàng)建一個實例,不能在類的外部new 出來,只能在類的內部中創(chuàng)建,就像中世紀那些歐洲的貴族女兒不外嫁,自產自銷
好處:
1.間少內存開銷
就像一個村子中家家戶戶都要喝水,但是不必每個人都個人家里都去挖一口井吧
2.方便控制
就像WEB 開發(fā),增刪查改這些操作都會寫一個公告的dao,不需要每個人都自己寫一套,控制方便呀
創(chuàng)建單例模式的方法
1.內部的構建函數(shù)私有化,不允許通過構建函數(shù)new 出來實例
2.在類的內部創(chuàng)建實例
3.提供獲取唯一實例的方法
常見的單例模式
1.餓漢式
餓漢模式的意思是,我先把對象(面包)創(chuàng)建好,等我要用(吃)的直接直接來拿就行了。
public class Singleton {
//先把對象創(chuàng)建好
private static final Singleton singleton = new Singleton();
//構造函數(shù)私有化
private Singleton() {
}
//其他人來拿的時候直接返回已創(chuàng)建好的對象
public static Singleton getInstance() {
return singleton;
}
}
2.懶漢式
懶漢模式的意思是,我先不創(chuàng)建類的對象實例,等你需要的時候我再創(chuàng)建。
public class Singleton {
//先不創(chuàng)建實例
private static Singleton singleton = null;
//構造函數(shù)私有化
private Singleton() {
}
//獲取對象的時候再進行實例化
public static Singleton getInstance() {
//加鎖,防止多個線程進來,都會判斷為null 然后都會創(chuàng)建多個實列,所以要加鎖,進行同步操作
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
return singleton;
}
}
3.雙重檢測模式
懶漢模式因為加鎖了,每個線程進來都會鎖住了,即使這個線程的實例已經存在了還被鎖住,這就不應該了哈,所以再加一層判斷不就好了
...
public static Singleton getInstance() {
if (singleton == null) {//先驗證對象是否創(chuàng)建,已經創(chuàng)建了直接返回
synchronized (Singleton.class) {//只有當對象未創(chuàng)建的時候才上鎖
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
4.靜態(tài)內部類懶漢式
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHoler.singleton;
}
//定義靜態(tài)內部類
private static class SingletonHoler {
//當內部類第一次訪問時,創(chuàng)建對象實例
private static Singleton singleton = new Singleton();
}
}
當外部去訪問這個單例的類的時候,靜態(tài)內部類是不會初始化的,就保證了資源不會被浪費,只有當SingletonHoler 方法被調用的時候才會去初始化這個類
為什么靜態(tài)內部類線程安全:
JVM虛擬機會保證一個類的構造器<clinit>()方法在多線程環(huán)境中被正確地加載,同步,如果多個線程同時去初始化一個類,那么只有一個線程去執(zhí)行這個類的構造器<clinit>()方法,其他線程都需要阻塞等待,直到活動線程執(zhí)行<clinit>()方法完畢。