終於理解單列模式了,單列模式和多執行緒
//2、單例類必須自己建立自己的例項。
//3、單例類必須為其他物件提供唯一的例項。
package Singleton;
//懶漢式 單例例項在第一次被使用時構建,延遲初始化。
public class singleton {
private static singleton sing =null; //1,表明這個類是不可能形成例項了。這主要是怕這個類會有多個例項。
public static singleton getInstance(){ //2,即然這個類是不可能形成例項,那麼,我們需要一個靜態的方式讓其形成例項:getInstance()
if(sing==null){ //3,在getInstance()中,先做判斷是否已形成例項,如果已形成則直接返回,否則建立例項, 我們取例項時,只需要使用Singleton.getInstance()就行了。
synchronized(singleton.class){//執行緒同步鎖,必須等一個執行緒訪問完,才能進行訪問
if(sing==null){//需要雙重鎖定,保證不會new兩次
sing=new singleton();//懶漢式:先初始化例項物件
}
}
}
return sing;
}
public void getName() {// 使用普通方法輸出皇帝的名字
System.out.println("單列模式:懶漢式");
}
}
//優點: 避免了餓漢式的那種在沒有用到的情況下建立事例,資源利用率高,不執行getInstance()就不會被例項,可以執行該類的其他靜態方法。
//缺點: 懶漢式在單個執行緒中沒有問題,但多個執行緒同事訪問的時候就可能同事建立多個例項,而且這多個例項不是同一個物件,雖然後面建立的例項會覆蓋先建立的例項,但是還是會存在拿到不同物件的情況。解決這個問題的辦法就是加鎖synchonized,第一次載入時不夠快,多執行緒使用不必要的同步開銷大。
//餓漢式 在自己內部定義自己的一個例項,只供內部呼叫
public class Singleton1
{
//2.提供一個全域性訪問點(其實就是一個全域性靜態欄位),外部可以通過該欄位訪問該類的唯一例項
//因為靜態欄位是屬於類的,所以這樣可以保證只有一個例項。
private static final Singleton1 only = new Singleton1();//單例例項在類裝載時就構建,急切初始化
//1 將建構函式宣告成私有的,這樣可以確保在類的外部無法例項化該類(即在類的外部獲取不到類的例項)
private Singleton1() {//私有(private)的建構函式,表明這個類是不可能形成例項了, 解釋:一個物件預設是存在一個隱式的帶無參的構造方法,預設是public,所以在new一個物件時,預設呼叫的隱式的建構函式,當建構函式私有時就不能例項化物件。構造方法作用初始化,方法名和類名一樣。建立物件都通過new
//do something
}
//這裡提供了一個供外部訪問本class的靜態方法,可以直接訪問
public static Singleton1 getInstance(){// 例項化引用
return only;
}
//測試用方法
public void put(){
System.out.println("單列模式:餓漢式");
}
//優點 1.執行緒安全
// 2.在類載入的同時已經建立好一個靜態物件,呼叫時反應速度快
//缺點
// 資源效率不高,可能getInstance()永遠不會執行到,但執行該類的其他靜態方法或者載入了該類(class.forName),那麼這個例項仍然初始化
}
public class test {
public static void main(String[] args) {
//將entry類的建構函式宣告為私有的建構函式,這樣我們在外部就無法通過Singleton s = new Singleton()來例項化該,因為Private生命的成員只有在該類的內部可以訪問。這樣可以保證類的例項只有一個(那就是在類的內部給它例項化)。
singleton sing = singleton.getInstance();
singleton sing1 = singleton.getInstance();
System.out.println(sing.equals(sing1));//指向同一個對像
sing.getName();//懶漢式例項物件輸出
sing1.getName();
System.out.println("-----------------------------------------");
Singleton1 s = Singleton1.getInstance();
Singleton1 s1 = Singleton1.getInstance();
s.put();//餓漢式例項物件輸出
s1.put();
System.out.println(s.equals(s1));//指向同一個對像
}