设计模式-单例模式

单例模式

  • 使用场景:
    • 要求生产唯一序列号。
    • WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
    • 创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

懒汉模式(线程不安全、不建议使用)

public class Singleton_01 {
    private static Singleton_01 instance;
    // 构造函数添加私有属性private,防止调用人员实例化
    private Singleton_01() { 
    }
    public static Singleton_01 getInstance(){
        // 多个线程同时执行到此处,instance为空,会创建出多个Singleton_01对象
        if (null != instance) {
            return instance;
        }
        // 返回实例化的对象
        return new Singleton_01();
    }
}
  • 在多线程情况下,有可能获取到多个实例化的对象。

懒汉模式(线程安全、不建议使用)

public class Singleton_02 {  
    private static Singleton_02 instance;
    // 构造函数添加私有属性private,防止调用人员实例化
    private Singleton_03 (){}
    // 加锁保证单例
    public static synchronized Singleton_02 getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}
  • 这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步

双重校验锁模式(线程安全、可以使用)

public class Singleton_03 {  
    private volatile static Singleton_03 singleton;  
    private Singleton_03 (){}  
    public static Singleton_03 getSingleton() {
    // 提前判断提高效率
    if (singleton == null) {  
        // 加锁保证单例
        synchronized (Singleton_03.class) {  
        if (singleton == null) {  
            singleton = new Singleton_03();  
        }  
        }  
    }  
    return singleton;  
    }  
}
  • 这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

饿汉模式(最简单、项目中最实用的模式、线程安全)

public class Singleton_04 {
    // 程序启动时直接创建对象
    private static Singleton_04 instance = new Singleton_04();
    // 构造函数添加私有属性private,防止调用人员实例化
    private Singleton_04() {
    }
    public static Singleton_04 getInstance() {
        return instance;
    }
}
  • 这个是以空间换时间的解决方案,也是最简单的方式,在内存足够大的情况下推荐使用这种方式。

静态内部类模式(线程安全、明确实现 lazy loading 效果)

public class Singleton_05 {
    // 内部类,jvm保证单例
    private static class SingletonHolder {  
    private static final Singleton_05 INSTANCE = new Singleton_05();  
    }  
    private Singleton_05 (){}  
    public static final Singleton_05 getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}
  • 即保证了懒加载又解决了加锁耗费性能的问题。
  • JVM可以保证多线程并发访问的正确性。

枚举模式(最佳方法、涉及到反序列化创建对象)

public enum Singleton_06 {  
    INSTANCE;  
    public static final Singleton_06 getInstance() {  
        return Singleton_06.INSTANCE;  
    }   
}
  • 它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化
posted @ 2021-05-11 18:11  jieya  阅读(56)  评论(0编辑  收藏  举报