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