天天看點

單列模式和多線程

//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));//指向同一個對像
        
    }