✅单例模式的多种写法

典型回答

想要实现一个单例,首先就是要考虑把构造函数设置成private的,否则的话就可以随时通过构造函数创建对象了,就不是单例了。

那把构造函数private之后,就还需要提供一个方法,可以初始化单例对象,并且要保证只能初始化一个单例对象。并且需要考虑线程安全的问题。

具体到写法上,主要有5种。分别是懒汉、饿汉、静态内部类、双重校验锁以及枚举。

扩展知识

懒汉

所谓懒汉,就是在需要的时候才会去创建对象。

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

好处就是避免提前创建浪费资源,但是缺点也明显,就是第一创建的时候浪费时间。

饿汉

所谓饿汉,就是在类刚一初始化的时候就立即把单例对象创建出来。

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

以上两种都是饿汉模式的具体实现。

静态内部类

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

枚举

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}  

✅为什么说枚举是实现单例最好的方式?

双重校验锁

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}  

✅有了synchronized为什么还需要volatile?

扩展知识

CAS实现单例

✅不使用synchronized和Lock如何设计一个线程安全的单例?

如何破坏单例

✅如何破坏单例模式?

原文: https://www.yuque.com/hollis666/xkm7k3/ggh2h0