原创

设计模式之单例模式

温馨提示:
本文最后更新于 2023年11月16日,已超过 433 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

单例模式是应用最广的设计模式之一,也是程序员最熟悉的一个设计模式。单例模式属于创建型模式,它提供了一种创建对象的最佳方式。

定义

保证一个类仅有一个实例,并提供一个访问它的全局访问点。例如:线程池、缓存、网络请求、数据库连接等。这些程序如果出现多实例,就可能出现异常情况。

优点

内存中仅有一个实例,减少内存开销、节约资源(尤其是频繁的创建和销毁实例),提高系统性能。

特点

  • 单例类有且仅有一个实例;
  • 单例类构造函数为private,不能通过外部new等方式创建实例;必须自己创建自己的唯一实例;
  • 单例类必须给其他所有类提供这一实例。

实现

饿汉式

public class Singleton {
    private Singleton(){}
    private static Singleton instance = new Singleton();
    public static Singleton getInstance(){
        return instance;
    }
}

饿汉式单例模式是最简单的实现方式,在类加载期间就已经将对象实例化了,所以是线程安全的。不过,这样的实现方式不支持延迟加载实例,如果自始至终都未使用此实例,则会造成内存浪费,因此不推荐使用

懒汉式

public class Singleton {
    private Singleton(){}
    private static Singleton instance;
    public static synchronized Singleton getInstance(){
        if (Objects.isNull(instance)){
            instance = new Singleton();
        }
        return instance;
    }
}

这种写法起到了懒加载的效果,能在多线程环境中正常工作,但由于加锁导致线程排队,使得代码效率受影响,因此不推荐使用

双重检查锁(推荐使用)

public class Singleton {
    private Singleton(){}
    private static volatile Singleton instance;
    public static Singleton getInstance(){
        if (Objects.isNull(instance)){
            synchronized(Singleton.class){
                if (Objects.isNull(instance)){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

双重检查锁是懒汉式单例模式的改进版本,既支持延迟加载、又保证了线程安全。

代码中两次if (Objects.isNull(instance))判断,在代码块中加锁使得instance有且仅有一次实例化操作,后面请求直接返回已经实例化的对象。

静态内部类(推荐使用)

public class Singleton {
    private Singleton(){}
    private static class Instance {
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance(){
        return Instance.INSTANCE;
    }
}

这种方式可达到双重检查锁同样效果,但实现更简单。它利用了classloader的机制来实现线程安全和延迟初始化。可理解为懒汉式的一种优雅实现方式。

当Singleton类被加载时并不一定会初始化INSTANCE,当调用了getInstance()方法时,Instance类被装载,从而实例化INSTANCE。此时由JVM来保证线程的安全性。

枚举(推荐使用)

public enum Singleton {
    INSTANCE
}

枚举不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。

正文到此结束
本文目录