设计模式之单例模式
温馨提示:
本文最后更新于 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
}
枚举不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
正文到此结束
- 本文标签: 设计模式
- 本文链接: https://www.58cto.cn/article/13
- 版权声明: 本文由程序言原创发布, 非商业性可自由转载、引用,但需署名作者且注明文章出处:程序言 》 设计模式之单例模式 - https://www.58cto.cn/article/13