单例模式:保证系统中一个类只有一个实例
1. 饿汉式单例
静态常量
/**
* 饿汉式单例:在类加载的初始化阶段就完成了实例化,使用JVM来解决了线程同步问题
* JVM中,初始化类时只有一个线程在操作
*/
public class HungrySingleton1 {
private static final HungrySingleton1 instance=new HungrySingleton1();
//私有构造方法,禁止在其他类中创建实例
private HungrySingleton1(){}
//静态工厂方法
public static HungrySingleton1 getInstance(){
return instance;
}
}
静态代码块
/**
* 饿汉式单例:在类加载的初始化阶段就完成了实例化,使用JVM来解决了线程同步问题
* JVM中,初始化类时只有一个线程在操作
*/
public class HungrySingleton2 {
private static HungrySingleton2 instance;
static {
instance = new HungrySingleton2();
}
//私有构造方法,禁止在其他类中创建实例
private HungrySingleton2() {}
public static HungrySingleton2 getInstance() {
return instance;
}
}
2. 懒汉式单例:
/**
* @Author Snail
* @Describe 懒汉式单例:双重校验加锁
* @CreateTime 2019/6/22
*/
public class LazySingleton {
private volatile static LazySingleton lazySingleton;
private LazySingleton() {
}
public static LazySingleton getInstance() {
if (lazySingleton == null) { //1
synchronized (LazySingleton.class) {
if (lazySingleton == null) { //2
lazySingleton = new LazySingleton();
}
}
}
return lazySingleton;
}
}
为什么要使用双重判断:
对于同步外的空判断(1处),可以提高系统性能。如果去掉后,单例类也能被安全创建,但在多线程竞争情况下,会出现多线程等待锁的情况;如果有判断是否为空,那么在一个线程创建完单例类,但未释放锁时,其他线程就不会去等待获取锁,而是直接去拿单例类。
对于同步内的空判断(2处),是保证单例类被安全创建必要的判断。
3. 双重判断加锁的单例注册表模式(spring中使用的方式):
使用HashMap存储单例类,使用双重判断加锁的方法,来保证只创建一个单例。
源码参考:https://www.cnblogs.com/nickup/p/9800120.html
Bean的五种作用域(scope):
singleton(默认,单例)
prototype(每次获取bean时,都会创建一个类)
session
request(每次请求都会创建要给新类)
global session
Bean作用域参考:https://blog.csdn.net/icarus_wang/article/details/51586776