天天看點

單例模式和多例模式(懶漢式和餓漢式)

一、什麼是單例、多例:

所謂單例就是所有的請求都用一個對象來處理,比如我們常用的service和dao層的對象通常都是單例的,而多例則指每個請求用一個新的對象來處理,比如action;

二、單例模式和多例模式說明:

  1. 單例模式和多例模式屬于對象模式。
  2. 單例模式的對象在整個系統中隻有一份,多例模式可以有多個執行個體。
  3. 它們都不對外提供構造方法,即構造方法都為私有。

三、單例模式适用場景:

  1. 需要生成唯一序列的環境
  2. 需要頻繁執行個體化然後銷毀的對象。
  3. 建立對象時耗時過多或者耗資源過多,但又經常用到的對象。
  4. 友善資源互相通信的環境

四、舉例

1、懶漢式

你用的時候,我再去給你建立對象

class Singleton{
      private static Singleton single;
      
      private static Singleton(){}

     public static synchronized Singleton getInstance(){
        if(single==null)
            single =new Singleton();
        return single;
    }
}
           

優點: 第一次調用才初始化,避免浪費記憶體

缺點: 加鎖了執行效率低

2、餓漢式

啟動的時候就建立了對象,

class SingleObj{
    //私有變量 
    private static SingleObj single=new SingleObj();          
   //私有構造函數 不能被執行個體化  
    private static SingleObj(){}

    public static SingleObj getInstance(){
    return single;    
  }      
}
           

優點: 沒有加鎖,執行效率更高

缺點: 類加載時就初始化,浪費記憶體

3、Double CheckLock實作單例:

Double CheckLock也就是雙重鎖判斷機制(由于JVM底層模型原因,偶爾會出問題,

不建議使用),是在懶漢式單例上發展而來

/**
*Double CheckLock實作單例
*Double CheckLock也就是雙重鎖判斷機制(由于JVM底層模型原因,
*偶爾會出問題,不建議使用)
*/

public class SingletonThree {
    
private volatile static SingletonThree instance;

//私有化構造器
private SingletonThree() {
}

//靜态工廠方法,雙重鎖判斷機制
public static SingletonThree newInstance() {
    if (instance== null) {
        synchronized (SingletonThree.class) {
            if (instance== null) {
                instance= new SingletonThree();
            }
        }
    }
return instance;
    }
}
           

4、靜态内部類模式:

特點:線程安全,調用效率高,可以延時加載

/**
*靜态内部類實作模式
*線程安全,調用效率高,可以延時加載
*/
public class SingletonFour {
    // 靜态内部類
    private static class SingletonClassInstance {
        private static final SingletonFour instance= new SingletonFour();
}

// 私有化構造器
    private SingletonFour() {

    }

//靜态工廠方法
    public static SingletonFour getInstance() {
        return SingletonClassInstance.instance;
    }
}
           

5、枚舉類:

特點: 線程安全,調用效率高,不能延時加載,可以天然的防止反射和反序列化調用;

描述: 這種實作方式還沒有被廣泛采用,但這是實作單例模式的最佳方法。它更簡潔,自動支援序列化機制,絕對防止多次執行個體化。

這種方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不僅能避免多線程同步問題,而且還自動支援序列化機制,防止反序列化重新建立新的對象,絕對防止多次執行個體化。不過,由于 JDK1.5 之後才加入 enum 特性,用這種方式寫不免讓人感覺生疏,在實際工作中,也很少用。

不能通過 reflection attack 來調用私有構造方法。

public class SingletonFive {

    //私有化構造器
    private SingletonFive(){

    }
    //使用枚舉
    private static enum Singleton{
        INSTANCE;

        private SingletonFive singleton;
        //JVM會保證此方法絕對隻調用一次
        private Singleton(){
            singleton = new SingletonFive();
        }
        public SingletonFive getInstance(){
            return singleton;
        }
    }

//靜态工廠方法
    public static SingletonFive getInstance(){
    return Singleton.INSTANCE.getInstance();
    }
}