单例模式——独一无二的对象

单例模式

1)简介
单例对象的类只允许一个实例存在,并提供一个全局访问点。
2)使用场景
有些对象只需要一个的时候,比如线程池、缓存、日志对象等。如果制造出多个实例,就会导致许多问题的产生。
3)为什么不使用全局变量 ?
虽然Java的静态对象可以做到,但如果将对象赋值给一个全局变量,那么我们必须在程序一开始就创建好对象。而恰巧这个对象非常消耗资源,程序在这次运行过程中又一直没有用到它,就会形成浪费。如果我们利用单例模式,我们就可以在需要时才创建对象(延迟实例化)。

最基本实现(懒汉式)

public class Singleton {
    private static Singleton uniqueInstance;   //利用静态对象记录类的唯一实例

    private Singleton() {}   //私有构造器

    //利用getInstance()方法实例化对象,并返回实例
    public static Singleton getInstance() {
        if(uniqueInstance == null) {
            uniqueInstance= new Singleton();
        }
        return uniqueInstance;

    //其他方法……
}
  • 私有的构造器可以确保无法从外部创建实例,只能够通过getInstance()方法创建实例。如果我们不需要这个实例,它就永远不会产生,这就是上文中所说的“延迟实例化”。
  • 这只是最基本的实现,它不支持多线程,因为没有加锁 synchronized。当有多个线程同时调用getInstance()方法时,就有可能创建出多个实例。

线程安全的实现(“双重检查加锁”)

public class Singleton {
    private volatile static Singleton uniqueInstance;

    private Singleton() {}

    public static getInstance() {
        if(uniqueInstance == null) {   //只有第一次实例化时,才会彻底执行以下的代码
            synchronized (Singleton.class) {
                if(uniqueInstance == null) {   //加入区块后,再检查一次
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

总结

文中共提到了两种实现单例模式的方式(一种线程不安全的懒汉式实现,一种线程安全的双锁式实现)。关于单例模式还有更多种的实现方式,当考虑使用何种方式时,这需要先确定在性能和资源上的限制,然后再选择适合自己的程序的方式去实现。

猜你喜欢

转载自blog.csdn.net/qq_34802416/article/details/79686525