1. 程式人生 > >Java單例設計模式的理解與常規實現方式

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));
  }
}

 

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