什么是單例?:其定義是單例對象的類只能允許一個實例存在
單例的實現基本原理:1.將該類的構造方法定義為私有訪問,不對外暴露從而使其他類不能實例化該類對象,只能通過該類的靜態方法得到該類的唯一實例 2.在該類中定義一個靜態方法(getInstance),當我們調用該方法時返回該類的實例對象
幾種實現方式:
餓漢式單例模式:
/**
- 餓漢式靜態常量式單例模式
- 優點:這種寫法在JVM裝載類的時候就實例化了,避免了線程同步的問題
- 缺點:在類裝載的時候就實例化,沒有達到延時加載的效果,造成內存浪費
- @author zhuys
*/
public class HungrySinglton {
//使用經常常量初始化實例
private final static HungrySinglton hungrySinglton = new HungrySinglton();
// 使用靜態塊初始化類的實例,與上面效果一致
// private static HungrySinglton hungrySinglton;
// static {
// hungrySinglton = new HungrySinglton();
// }
private HungrySinglton() {};
public static HungrySinglton getInstance() {
return hungrySinglton;
}
}
懶漢式單例模式(非同步):
/**
- 懶漢式單例模式:非同步
- 優點:在調用的時候初始化該單例
- 缺點:並非線程同步,不建議使用
- @author zhuys
*/
public class LazySingleton {
private static LazySingleton lazySingleton;
private LazySingleton() {};
public static LazySingleton getInstance() {
if(lazySingleton == null) {
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
懶漢式單例(同步):
/**
- 懶漢式單例模式:同步
- 優點:在調用的時候初始化該單例並實現線程同步
- @author zhuys
*/
public class LazySyncSingleton {
private static LazySyncSingleton lazySingleton;
private LazySyncSingleton() {};
//法1:該方式使用synchronized同步鎖將整個方法同步 實現線程同步 但同步整個方法在高並發的情況下會造成阻塞
//效率低下,不推薦使用
public static synchronized LazySyncSingleton getInstance1() {
if(lazySingleton == null) {
lazySingleton = new LazySyncSingleton();
}
return lazySingleton;
}
//法2:使用synchronized同步實例化改單例的代碼塊;但該方法不能完全實現同步,可能會產生多個實例;例如:在第一次創建時
//多個線程同時進入if(lazySingleton == null) 則會產生多個實例 不推薦使用
public static LazySyncSingleton getInstance2() {
if(lazySingleton == null) {
synchronized (LazySyncSingleton.class) {
lazySingleton = new LazySyncSingleton();
}
}
return lazySingleton;
}
//法3:雙重檢查法,同步代碼塊中再次檢查一次是否w為null解決了上述問題 推薦使用
public static LazySyncSingleton getInstance3() {
if(lazySingleton == null) {
synchronized (LazySyncSingleton.class) {
if(lazySingleton == null) {
lazySingleton = new LazySyncSingleton();
}
}
}
return lazySingleton;
}
}
內部類單例模式:
package pers.ly.learn.designModel.singleton;
/**
- 靜態內部類單例模式:
- 靜態內部類方式在InnerSingleton類被裝載時並不會立即實例化
- 因為靜態內部類是在調用的時候才會實例化,這樣就達到了延時加載節省資源的效果
- 另外在靜態內部類中通過靜態常量初始化該單例又到達了保證其唯一性的效果
- 優點:避免了線程不安全,延遲加載,效率高。 推薦使用
- @author zhuys
*/
public class InnerSingleton {
private InnerSingleton() {};
private static class InnerSingletonInstance{
private final static InnerSingleton innerSingleton = new InnerSingleton();
}
public static InnerSingleton getInstance() {
return InnerSingletonInstance.innerSingleton;
}
}