单例模式的实现

单例模式的实现


是什么

单例模式指一个类有且仅有一个实例,并且自行实例化向整个系统提供。因此 1、构造器需要私有化 2、实例需要用静态变量保存且自行创建 3、需要向外提供实例

两种形式

1、饿汉式:直接创建对象,不存在线程安全问题

  • 直接实例化式
  • 枚举式
  • 静态代码块式

2、懒汉式:延迟创建对象

  • 线程不安全方式
  • 线程安全方式
  • 静态内部类方式

代码实现

/**
 * 1.1 
 * 直接实例化
 */
public class SingletonDemo1 {
    public static final SingletonDemo1 INSTANCE = new SingletonDemo1();
    private SingletonDemo1() {
    }
}

/**
 * 1.2 
 * 枚举类型表示该类型的对象是有限的几个,我们限定为一个,就成了单例模式
 * 枚举类型的构造默认私有化
 */
public enum SingletonDemo2 {
    INSTANCE;
}

/**
* 1.3 
* 引入配置文件来对实例的一些内部信息进行进行初始化
* 适用于需要进行复杂实例化的类
*/
public class SingletonDemo3 {
    public static final SingletonDemo3 INSTANCE;
    private String info;

    static {
        Properties pro = new Properties();
        try {
            pro.load(SingletonDemo3.class.getClassLoader().getResourceAsStream("singleton.properties"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        INSTANCE = new SingletonDemo3(pro.getProperty("info"));
    }

    public String getInfo() {
        return info;
    }

    private SingletonDemo3(String info) {
        this.info = info;
    }
}

添加 volatile 是为了防止指令重排,比如 instance = new Singleton() 语句就分为三个步骤 1. 给 instance 分配内存 2. 通用构造方法进行 初始化 3. 将 instance 指向分配的内存空间,这三个步骤在 JVM 编译的时候不能够保证顺序执行,这就是指令重排


/*
* 2.1
* 对外提供方法获取实例
* 用 if 条件判断来保证单实例
* 存在安全问题
*/
public class SingletonDemo4 {
    private volatile static final SingletonDemo4 instance;
    private SingletonDemo4() {
    }
    public static SingletonDemo4 getInstance(){
        if (instance == null) {
            instance = new SingletonDemo4();
        }
        return instance;
    }
}

/**
* 2.2 
* 双重校验实现单例模式
* 线程安全
*/
public class SingletonDemo5 {
    private volatile static final SingletonDemo5 instance;
    private SingletonDemo5() {

    }
    public static SingletonDemo5 getInstance(){
        if (instance == null) {
            synchronized (SingletonDemo5.class) {
                if (instance == null) 
                	instance = new SingletonDemo5();
            }
        }

        return instance;
    }
}

/**
 * 2.3 
 * 推荐使用方式
 * 在内部内被加载和初始化的时候,才创建对象
 * 静态内部内不会随着外部类的加载和初始化而初始化,需要单独加载
 */
public class SingletonDemo6 {
    private SingletonDemo6() {
    }
    private static class Inner {
        private volatile static final SingletonDemo6 INSTANCE = new SingletonDemo6();
    }

    public static SingletonDemo6 getInstance() {
        return Inner.INSTANCE;
    }
}

参考:单例设计模式

posted @ 2021-03-25 15:40  心平气和Coding  阅读(57)  评论(0)    收藏  举报