单例模式(五种实现方式)

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,该模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。

注意:

  • 作用:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
  • 主要解决:一个全局使用的类频繁地创建与销毁。
  • 何时使用:当您想控制实例数目,节省系统资源的时候。
  • 关键代码:构造函数是私有的。

实现方式:

(1)饿汉模式:线程安全、调用效率高、但不能延时加载

class Singleton_Hungry{

    private static Singleton_Hungry instance  = new Singleton_Hungry();
    
    // 构造器私有化
    private Singleton_Hungry(){};

    // 创造公有方法调用instance
    private static Singleton_Hungry getSingleton(){
            return instance;
        }
    }

直接把单例对象创建出来了,要用的时候直接返回即可。但是问题也比较明显。单例在还没有使用到的时候,初始化就已经完成了。也就是说,如果程序从头到位都没用使用这个单例的话,单例的对象还是会创建。这就造成了不必要的资源浪费。所以不推荐这种实现方式。

好处是没有线程安全的问题,坏处是浪费内存空间。

(2)懒汉模式:线程安全,调用效率不高,但是能延时加载

public class Singleton_Lazy {

    //类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)
    private static Singleton_Lazy instance;

    //构造器私有化
    private Singleton_Lazy(){}

    //方法同步,调用效率低
    public static synchronized Singleton_Lazy getInstance(){
        if(instance==null){
            instance=new Singleton_Lazy();
        }
        return instance;
    }
}

优点: 只有在使用时才会实例化单例,一定程度上节约了资源。
缺点: 第一次加载时要立即实例化,反应稍慢。每次调用getInstance()方法都会进行同步,这样会消耗不必要的资源这种模式一般不建议使用。

(3)静态内部类:线程安全,调用效率高,能延时加载

public class Singleton_static {
    private Singleton_static() {
    }

    // 静态内部类
    private static class SingletonHolder {
        private static Singleton_static instance = new Singleton_static();
    }
    
    public static Singleton_static getInstance() {
        return SingletonHolder.instance;
    }
}

第一次加载Singleton类时不会初始化instance,只有在第一次调用getInstance()方法时,虚拟机会加载SingletonHolder类,初始化instance。

(4)枚举类:线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化调用

public enum Singleton_enum {

            //枚举元素本身就是单例
            INSTANCE;

            //添加自己需要的操作
            public void singletonOperation(){
            }
 }

默认枚举实例的创建是线程安全的,即使反序列化也不会生成新的实例,任何情况下都是一个单例。简单。

(5)Double CheckLock(双重锁判断机制):线程安全,能延时加载

public class Singleton{
    private static volatile Singleton singleton;
    private Singleton(){};
    private static Singleton getSingleton(){
        if(singleton==null){
            // 改进加锁懒汉式,锁加在if判断语句后,可减少锁的使用
            synchronized(Singleton.class){
                if(singleton==null){
                    singleton=new Singleton();
                }
            }
        }
        return singleton;
    }
}

双重锁判断机制,综合了懒汉式和饿汉式两者的优缺点整合而成。看上面代码实现中,特点是在synchronized关键字内外都加了一层 if 条件判断,这样既保证了线程安全,又比直接上锁提高了执行效率,还节省了内存空间。

猜你喜欢

转载自blog.csdn.net/weixin_47465999/article/details/119565638