单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在单例模式中,内存中只会创建且仅创建一次对象在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。 ~ 本篇内容包括:关于单例模式、单例模式-饿汉式实现、单例模式-懒汉式实现
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在单例模式中,内存中只会创建且仅创建一次对象在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。
Ps:在 Spring 中,每个 Bean 默认就是单例的,这样的优点是 Spring 容器可以管理这些 Bean 的生命周期,决定什么时候创建出来,什么时候销毁,销毁的时候如何处理等等。
单例模式有两种类型:
# 单例模式的优点
# 单例模式的缺点
所谓饿汉式也就是在类加载的时候直接 new 出一个对象来,不管以后用不用得到,是一种以空间换取时间的策略。
public class Singleton {
/**
* 定义一个变量来存储创建好的实例,直接在这里创建实例,只能创建一次,
* static 变量在类加载时进行初始化,并且只被初始化一次。
*/
private static final Singleton INSTANCE = new Singleton();
/**
* 私有化构造方法,可以在内部控制创建实例的数目,防止在外部创建
*/
private Singleton() {
}
/**
* 定义一个方法为客户端提供类实例,方法上加static将该方法变为静态,目的是不需要对象实例就可以在外部直接通过类来调用
*/
public static Singleton getInstance() {
// 直接使用已经创建好的实例
return INSTANCE;
}
}
public class Singleton {
/**
* 在成员位置创建该类的对象
*/
private static final Singleton INSTANCE;
/**
* 私有构造方法
*/
private Singleton() {
}
static {
// 静态代码块随着类的加载而加载,并且只加载一次,它的优先级与静态成员变量一致,谁先声明谁就先执行
INSTANCE = new Singleton();
}
/**
* 对外提供静态方法获取该对象
*/
public static Singleton getInstance() {
return INSTANCE;
}
}
public enum Singleton {
/**
* Java 的枚举类型实质上时功能齐全的类,因此可以有自己的属性和方法
* 定义一个枚举的元素,它就代表了 Singleton 的一个实例
*/
INSTANCE;
/**
* 单例自己的操作函数
*/
public void singletonOperation() {
// 功能处理
}
}
顾名思义,懒汉式指只有当该实例被使用到的时候才会创建。
public class Singleton {
/**
* 私有构造方法
*/
private Singleton() {
}
/**
* 在成员位置声明Singleton类型的静态变量,并没有进行对象的赋值操作
*/
private static Singleton instance;
/**
* 当调用 getInstance() 方法获取 Singleton 类的对象的时候才创建 Singleton 类的对象,这样就实现了懒加载的效果。
*
* @return Singleton
*/
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public class Singleton {
/**
* 私有构造方法
*/
private Singleton() {
}
/**
* 在成员位置创建该类的对象
*/
private static Singleton instance;
/**
* 对外提供静态方法获取该对象,加了synchronized关键字,线程安全(但是导致该方法的执行效果特别低)
*
* @return Singleton
*/
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public class Singleton {
/**
* 私有构造方法
*/
private Singleton() {
}
/**
* 在成员位置创建该类的对象
* 使用 volatile :避免 JVM 在实例化对象的时候会进行优化和指令重排序操作而导致空指针问题
*/
private static volatile Singleton instance;
/**
* 对外提供静态方法获取该对象
*
* @return Singleton
*/
public static Singleton getInstance() {
// 第一次判断,如果instance不为null,不进入抢锁阶段,直接返回实例
if (instance == null) {
synchronized (Singleton.class) {
// 抢到锁之后再次判断是否为null
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
public class Singleton {
/**
* 私有构造方法
*/
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
/**
* 对外提供静态方法获取该对象
* 第一次加载 Singleton 类时不会去初始化 INSTANCE,只有第一次调用 getInstance,虚拟机加载 SingletonHolder,初始化 INSTANCE
* 这样不仅能确保线程安全,也能保证 Singleton 类的唯一性
*
* @return Singleton
*/
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
静态内部类单例模式是一种优秀的单例模式,是开源项目中比较常用的一种单例模式。在没有加任何锁的情况下,保证了多线程下的安全,并且没有任何性能影响和空间的浪费。