单例模式保证一个类只有一个对象被创建,所创建的对象可以被直接访问,不需要实例化。

解决问题:一个类被频繁地创建与销毁。

如何解决:判断单利类的实力是否已经存在,存在则返回,不存在则创建。

实现方法:构造函数设为私有,类内创建实例,类外保证不能创建实例

优点:

  1. 减少内存开销,避免一个类被多次创建与销毁
  2. 避免对资源的多重占用

缺点:没有接口,不能继承,与单一职责冲突

实现步骤:

1
2
3
4
5
6
7
8
9
10
11
12
public class SingleObject{
// 类内创建实例
private static volatile SingleObject singleInstance = new SingleObject();

// 设置构造函数为私有
private SingleObject(){}

// 设置获取唯一可用对象的方法
public static SingleObject getSingleInstance(){
return singleInstance;
}
}
1
2
3
4
5
6
public class SingletonDemo{
public static void main(String[] args){
// 注:不需要创建,直接获取。
SingleObject object = SingleObject.getSingleInstance();
}
}

单例模式的几种实现方式

懒汉式1 ❌ 懒汉式2 双检锁/双重校验锁(DCL,即 double-checked locking)
懒加载
线程安全
描述 在调用 getInstance 方法时才进行实例化,无法保证线程安全 懒加载,第一次调用 getInstance 方法才实例化,使用 synchronized 保证线程安全。 懒加载,第一次调用 getInstance 方法才实例化,通过双锁机制实现线程安全
优点 /
缺点 不能保证线程安全 synchronized
实现 public class Singleton{ private static volatile Singleton singletonInstance; private Singleton(){} public static Singleton getSingletonInstance(){ if(singletonInstance == null) singletonInstance = new Singleton(); return singletonInstance; } } public class Singleton{ private static volatile Singleton instance; private Singleton(){} public static synchronized Singleton getInstance(){ if(instance == null ) instance = new Singleton; return instance; } } public class Singleton{ private static volatile Singleton instance; private Singleton(){} public static Singleton getInstance(){ if(instance == null){ synchronized(Singleton.class){ if(instance == null) instance = new Singleton(); } } return instance; } }
饿汉式 登记式/静态内部类 枚举
懒加载
线程安全
实例化时机 类被加载时 instance 就被初始化 通过在类内部使用静态内部类,在调用getInstance 方法时才会装载内部类,实现延迟初始化(懒加载)
优点 相比较加锁的懒汉式实现方式,没有 synchronized ,效率会提高 解决了 不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
缺点 类加载时就会初始化,易产生垃圾对象导致一定程度的内存浪费,
实现 public class Singleton(){ private static volatile Singleton instance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return instance; } } private class Singleton{ private static class SingletonHolder{ public static final Singleton INSTANCE = new Singleton(); } private Singelton(){} public static final Singleton getInstance(){ return SingletonHolder.INSTANCE; } } private enum Singleton{ INSTANCE; }