详解单例模式多种实现方式及其特性(饿汉/懒汉/双重检测锁/静态内部类/枚举/注册式)

/**
 * 单例模式
    将构造函数私有化
    在类的内部创建实例
    提供获取唯一实例的方法
 */
// 创建想要实现单例设计的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);
            }
        }
    }
}
posted @ 2021-01-11 21:14  钟子期  阅读(146)  评论(0)    收藏  举报