一、什麼是單例、多例:
所謂單例就是所有的請求都用一個對象來處理,比如我們常用的service和dao層的對象通常都是單例的,而多例則指每個請求用一個新的對象來處理,比如action;
二、單例模式和多例模式說明:
- 單例模式和多例模式屬于對象模式。
- 單例模式的對象在整個系統中隻有一份,多例模式可以有多個執行個體。
- 它們都不對外提供構造方法,即構造方法都為私有。
三、單例模式适用場景:
- 需要生成唯一序列的環境
- 需要頻繁執行個體化然後銷毀的對象。
- 建立對象時耗時過多或者耗資源過多,但又經常用到的對象。
- 友善資源互相通信的環境
四、舉例
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();
}
}