目录
一、前言
单例模式为Java设计模式中的一种,单例模式是提供给不需要记录状态的实例的一种设计模式。
在这种设计模式下,所有的对象调用不需要再重复的创建和销毁对象,这种流式化的操作类似于面向过程编程。
从而优化性能。
二、饿汉式
顾名思义,饿汉式在类加载的初期便将对象创建出来(如果这里不清楚的可能对类加载机制存在知识缺漏,这里不展开说明),并且控制构造方法的调用,从而实现jvm中只存在一个实例,具体实现如下:
public class Single {
//私有化构造器
private Single(){}
//定义一个静态变量,用来存储实例对象
private static final Single instance = new Single();
//静态方法,返回实例对象
public static Single getInstance(){
return instance;
}
}
三、懒汉式
顾名思义,懒汉式在类加载时并不会创建实例,而是在使用到时才会去创建实例,同时为保持jvm中只有一个对象,依然需要控制构造方法的调用,并提供获取唯一实例的方法,具体实现如下:
public class SingleLazy {
//私有化构造方法
private SingleLazy(){}
//初始化静态实例对象
private static SingleLazy instance;
//对外提供公共的静态方法
public static SingleLazy getInstance(){
if(instance == null){
//“1”
instance = new SingleLazy();
}
return instance;
}
}
熟悉多线程的小伙伴可能能发现,这种模式下在多线程的场景下容易出现创建的实例不为一的情况, 多线程通过if后到达“1”处,instance的值会被多次创建,进而出现线程安全问题。
四、Double-checked locking
顾名思义,双检查锁这种设计方式中包含了两个锁,这种设计方式就是来解决懒汉式存在线程安全的问题。我们先看如何实现:
public class SingleDoubleLock {
//私有化构造器
private SingleDoubleLock(){}
//初始化静态实例
private static volatile SingleDoubleLock instance = null;
//创建获取实例方法
public static SingleDoubleLock getInstance(){
if(instance == null)
synchronized (SingleDoubleLock.class) {
if (instance == null)
instance = new SingleDoubleLock();
}
return instance;
}
}
在这里静态对象被volatile修饰,volatile主要是来解决指令重排与可见性问题,这里不过多扩展。双重检查的实现是两个if,第一个if主要是解决性能问题,来避免代码重复串行,只在创建实例前来进行锁操作。从而提升代码性能。
五、场景
在springBoot中单例模式被广泛使用,在我们经常接触到的业务场景中,例如我们经常注入的service、mapper都是双重检查锁的这种模式。