设计模式--单例模式--懒汉饿汉

单例模式

单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式

通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

结构图

Singleton类,定义一个负责GetInstance操作,允许客户访问它的唯一实例。GetInstance是一个静态方法,主要负责创建自己的唯一实例。

java 复制代码
public class Singleton {
    
    private static Singleton instatnce;

    private Singleton() {   // 无参构造私有化,防止外部new对象
    }
    
    // 得到Singleton的实例,唯一的途径
    public static Singleton getInstance() { 
        if (instatnce == null) {
            instatnce = new Singleton();
        }
        return instatnce;
    }
}

客户端

java 复制代码
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();

if (s1 == s2) {
    System.out.println("对象相同");
}

多线程

另外还需要注意一些细节,比如,多线程的程序中,多个线程同时访问Singleton类,调用getInstance()方法时,会可能创建多个实例。我们需要加一些锁。

java 复制代码
public synchronized static Singleton getInstance() {
    if (instatnce == null) {
        instatnce = new Singleton();
    }
    return instatnce;
}

使用synchronized关键字锁住此方法,使得此方法在同一个时间点只有一个线程能进入访问。

这样看起来也没有问题,但是会有一个性能的问题:每次调用此方法的时候都需要锁,但其实我们只需要在创建instance 的时候让一个线程去创建就行。那么再改造一下。

双重锁定

java 复制代码
public class Singleton {

    private volatile static Singleton instatnce;

    private Singleton() {   // 无参构造私有化,防止外部new对象
    }

    // 得到Singleton的实例,唯一的途径
    public static Singleton getInstance() {
        if (instatnce == null) {
            synchronized (Singleton.class){	// 防止多个线程进入创建实例
                if (instatnce == null) {
                    instatnce = new Singleton();
                }
            }
        }
        return instatnce;
    }
}

使用volatile关键字,当synchronized变量被初始化成Singleton时,多个线程能正确处理synchronized变量。

synchronized 代码块儿中,还需要再加一层对instance的判断,因为当多个线程访问此方法时,它们都是通过了第一层instance==null的判断的,里面再加一层判断,防止后进入的线程又一次去创建实例。

静态初始化

在实际应用中,上面的做法都能应付自如。不过为了确保实例唯一,还是会带来很大的性能代价。对于性能要求很高的程序,建议还是采用静态初始化,也就是饿汉模式。

java 复制代码
public class Singleton {

    private static Singleton instatnce = new Singleton();

    private Singleton() {   // 无参构造私有化,防止外部new对象
    }

    // 得到Singleton的实例,唯一的途径
    public static Singleton getInstance() {
        return instatnce;
    }
}

这种静态初始化的方式是在自己被加载时就将自己实例化,所以被形象称之为饿汉式单例类。

要在第一次被引用时,才将自己实例化,则是被称之为懒汉式单例类。

大多数情况都是选择使用饿汉模式单例类,实际按项目需求做出选择。

相关推荐
马剑威(威哥爱编程)32 分钟前
读写锁分离设计模式详解
java·设计模式·java-ee
修道-032333 分钟前
【JAVA】二、设计模式之策略模式
java·设计模式·策略模式
G皮T4 小时前
【设计模式】结构型模式(四):组合模式、享元模式
java·设计模式·组合模式·享元模式·composite·flyweight
W_Meng_H4 小时前
设计模式-组合模式
设计模式·组合模式
无尽的大道9 小时前
单例模式详解:如何优雅地实现线程安全的单例
单例模式
吾与谁归in14 小时前
【C#设计模式(8)——过滤器模式(Adapter Pattern)】
设计模式·c#·过滤器模式
G皮T15 小时前
【设计模式】行为型模式(一):模板方法模式、观察者模式
java·观察者模式·设计模式·模板方法模式·template method·行为型模式·observer
iFlyCai18 小时前
23种设计模式的Flutter实现第一篇创建型模式(一)
flutter·设计模式·dart
zhouzhihao_0718 小时前
程序代码设计模式之模板方法模式(1)
java·设计模式·模板方法模式
xianwu54318 小时前
【设计模式】工厂模式
开发语言·c++·设计模式·简单工厂模式·抽象工厂模式