Java單例設計模式的理解與常規實現方式

1:Java中單例模式是一種常見的設計模式,單例模式有以下特點:

  單例類只能有一個實例。

  單例類必須自己創建自己的唯一實例。 單例類必須給所有其他對象提供這一實例。

  單例模式確保某個類只有一個實例,而且自行實例化並向整個系統提供這個實例。

2:java中單例模式的寫法也有很多種,我在這裏列舉幾張常用的方式:

 1、餓漢式,線程安全 但效率比較低:

/**

  • 單例模式的實現:餓漢式,線程安全 但效率比較低
    */

public class SingletonTest {

// 定義一個私有的構造方法
private SingletonTest() {  
}  

// 將自身的實例對象設置爲一個屬性,並加上static和final修飾符
private static final SingletonTest instance = new SingletonTest();  

// 靜態方法返回該類的實例
public static SingletonTest getInstancei() {  
    return instance;  
}  

}

 2、懶漢式,非線程安全:

/**

  • 單例模式的實現:懶漢式,非線程安全
  • */

public class SingletonTest {

// 定義私有構造方法(防止通過 new SingletonTest()去實例化)
private SingletonTest() {   
}   

// 定義一個SingletonTest類型的變量(不初始化,注意這裏沒有使用final關鍵字)
private static SingletonTest instance;   

// 定義一個靜態的方法(調用時再初始化SingletonTest,但是多線程訪問時,可能造成重複初始化問題)
public static SingletonTest getInstance() {   
    if (instance == null)   
        instance = new SingletonTest();   
    return instance;   
}   

}

 3、懶漢式,線程安全簡單實現  :

/**

  • 單例模式的實現:懶漢式,線程安全簡單實現
  • */

public class SingletonTest {

// 定義私有構造方法(防止通過 new SingletonTest()去實例化)
private SingletonTest() {   
}   

// 定義一個SingletonTest類型的變量(不初始化,注意這裏沒有使用final關鍵字)
private static SingletonTest instance;   

// 定義一個靜態的方法(調用時再初始化SingletonTest,使用synchronized 避免多線程訪問時,可能造成重的復初始化問題)
public static synchronized  SingletonTest getInstance() {   
    if (instance == null)   
        instance = new SingletonTest();   
    return instance;   
}   

}

 4、線程安全 並且效率高  單例模式最優方案

/**

  • 單例模式最優方案
  • 線程安全 並且效率高
  • */

public class SingletonTest {

// 定義一個私有構造方法
private SingletonTest() { 
 
}   
//定義一個靜態私有變量(不初始化,不使用final關鍵字,使用volatile保證了多線程訪問時instance變量的可見性,避免了instance初始化時其他變量屬性還沒賦值完時,被另外線程調用)
private static volatile SingletonTest instance;  

//定義一個共有的靜態方法,返回該類型實例
public static SingletonTest getIstance() { 
    // 對象實例化時與否判斷(不使用同步代碼塊,instance不等於null時,直接返回對象,提高運行效率)
    if (instance == null) {
        //同步代碼塊(對象未初始化時,使用同步代碼塊,保證多線程訪問時對象在第一次創建後,不再重複被創建)
        synchronized (SingletonTest.class) {
            //未初始化,則初始instance變量
            if (instance == null) {
                instance = new SingletonTest();   
            }   
        }   
    }   
    return instance;   
}   

}

 5、靜態內部類方式

/**

  • 靜態內部類方式
    *

*/
public class Singleton {

 private static class SingletonTest {  
 private static final Singleton INSTANCE = new Singleton();  
 }  
 private Singleton (){}
 public static final Singleton getInstance() {  
     return SingletonTest.INSTANCE;  
 }  

}
以上單例如設計模式即使有多重檢查鎖也可以通過反射破壞單例

6、目前最爲安全的實現單例的方法是通過內部靜態enum的方法來實現,因爲JVM會保證enum不能被反射並且構造器方法只執行一次,事例如下:

/**

  • 使用枚舉的單例模式
    *
  • @author uu
    */

public class EnumSingleton{

private EnumSingleton(){}
public static EnumSingleton getInstance(){
    return Singleton.INSTANCE.getInstance();
}

private static enum Singleton{
    INSTANCE;
    
    private EnumSingleton singleton;
    //JVM會保證此方法絕對只調用一次
    private Singleton(){
        singleton = new EnumSingleton();
    }
    public EnumSingleton getInstance(){
        return singleton;
    }
}

public static void main(String[] args) {

EnumSingleton obj0 = EnumSingleton.getInstance();
EnumSingleton obj1 = EnumSingleton.getInstance();
//輸出結果:obj0==obj1?true
System.out.println("obj0==obj1?" + (obj0==obj1));

}
}

在此淺談一下個人理解,希望對大家有所幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章