詳解單例模式多種實現方式及其特性(餓漢/懶漢/雙重檢測鎖/靜態內部類/列舉/註冊式)
阿新 • • 發佈:2021-01-11
/**
* 單例模式
將建構函式私有化
在類的內部建立例項
提供獲取唯一例項的方法
*/
// 建立想要實現單例設計的Java類,如下:
public class SingletonModel {
private SingletonModel(){
System.out.println("model 被建立");
}
private SingletonModel(int i){
}
餓漢
private static final SingletonModel hungry = new SingletonModel(); public static SingletonModel getInstance() { return hungry; }
懶漢
private static SingletonModel lazyBoy1 = null;
public static SingletonModel getInstance() {
if(lazyBoy1==null){
lazyBoy1 = new SingletonModel();
}
return lazyBoy1;
}
雙重檢測鎖
private static volatile SingletonModel lazyBoyDoubleCheckLock = null; public static SingletonModel getInstance() { if(lazyBoyDoubleCheckLock==null){//僅第一次建立才需要加鎖 synchronized (SingletonModel.class){ if(lazyBoyDoubleCheckLock==null) lazyBoyDoubleCheckLock = new SingletonModel();//不是原子操作的話,需要加volatile禁止重排序 } } return lazyBoyDoubleCheckLock; }
靜態內部類
private static class InnerClass{ //private static Integer oo = 1; private static SingletonModel obj = new SingletonModel(); } public static SingletonModel getInstance() { return InnerClass.obj; } public static void main(String[] args) { SingletonModel sg = new SingletonModel(1); System.out.println("sg inited"); SingletonModel.getInstance(); SingletonModel.getInstance(); int i = 1; } }
註冊式-列舉單例
// 列舉式單例模式也是 Effective Java 書中推薦的一種單例模式實現寫法。JDK 列舉的語法特殊性質及繁殖也為列舉報價護航,讓列舉式單例模式成為一種比較優雅的實現。
public enum EnumSingleton {
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
}
註冊式-容器式單例
// 看起來比較麻煩,適用於單例例項非常多的情況
public class ContainerSingleton {
private ContainerSingleton(){}
private static Map<String,Object> ioc = new ConcurrentHashMap<String,Object>();
public static Object getBean(String className){
synchronized (ioc){
if(!ioc.containsKey(className)){
Object obj = null;
try{
obj = Class.forName(className).newInstance();
ioc.put(className, obj);
}catch (Exception e){
e.printStackTrace();
}
return obj;
} else {
return ioc.get(className);
}
}
}
}