一、简单介绍
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
- 1、单例类只能有一个实例。
- 2、单例类必须自己创建自己的唯一实例。
- 3、单例类必须给所有其他对象提供这一实例。
二、实现方法
(一)、饿汉式
行如其名,不管需不需要用到实例,都去创建实例,但会造成空间浪费
1、静态常量
class Singleton {
// 唯一实例
private final static Singleton INSTANCE = new Singleton();
// 构造器私有,不允许外部实例化
private Singleton(){}
public static Singleton getInstance() {
return INSTANCE;
}
}
2、静态代码块
class Singleton {
// 唯一实例
private final static Singleton INSTANCE;
static {
INSTANCE = new Singleton();
}
// 构造器私有,不允许外部实例化
private Singleton(){}
public static Singleton getInstance() {
return INSTANCE;
}
}
(二)、懒汉式
行如其名,等到需要创建实例的时候,再去创建实例
1、简单实现(线程不安全)
class Singleton {
private static Singleton instance;
// 构造器私有,不允许外部实例化
private Singleton(){}
// 等到外部调用才创建实例,但是在if代码块中,会有线程不安全的问题
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2、方法同步
class Singleton {
private static Singleton instance;
// 构造器私有,不允许外部实例化
private Singleton(){}
// 与上面的区别,多了一个synchronized,保证线程安全
// 但这个锁粒度太大,每次想取实例对象的时候,都需要进行锁操作
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
(三)、双重校验锁(DCL,double-checked locking)
综合以上饿汉式和懒汉式的缺点,这种方式采用双锁机制进行优化,安全且在多线程情况下能保持高性能。
class Singleton {
// 这里用了volatile关键字的可见性
// 保证一个线程创建出来的实例能被其他线程立即感知到
// 同时也禁止指令重排序,保证new Singleton()指令的顺序
// 其他线程不会访问到一个未初始化的对象,从而保证安全性
private static volatile Singleton instance;
// 构造器私有,不允许外部实例化
private Singleton(){}
public static Singleton getInstance() {
// 第一次if校验,可能会有多个线程通过
if (instance == null) {
// 多个线程抢占锁
synchronized (Singleton.class) {
// 第二次if校验(禁止指令重排序,保证了只有第一个进入该代码块的线程可以通过),
// 并创建实例对象,被其他线程感知,之后其他线程都无法进入第二个if代码块
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
(四)、静态内部类
这种方式是Singleton类被类加载器装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有通过显式调用getInstance方法时,才会显式装载SingletonHolder类,从而实例化instance。
class Singleton {
// 静态内部类
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
// 构造器私有,不允许外部实例化
private Singleton() {}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
(五)、枚举类
这是实现单例模式的最佳方法,但在实际工作中很少用。它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
enum Singleton {
INSTANCE;
}
全文结。希望大家多多支持,点个赞就好,哈哈。