1. 程式人生 > >終於理解單列模式了,單列模式和多執行緒

終於理解單列模式了,單列模式和多執行緒

//1、單例類確保自己只有一個例項(構造方法私有化)
//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));//指向同一個對像
        
    }