一、什么是单例模式
在很多场景下,我们在整个软件的生命周期中只需要一个实例即可,创建多了不仅会造成执行变慢(虽然创建一个对象慢不了多久)还会造成内存的浪费。所以需要由单例模式。
二、单例模式如何实施
形式一:预加载模式
预加载就是在类被加载到到jvm的时候就将对象创建好,这种方式由jvm自身来保证并发状态下安全性。但是这个
public class PreSingleton {
private static final PreSingleton instance = new PreSingleton();
private PreSingleton() {}
public static PreSingleton getInstance() {
return instance;
}
}
形式二:基于双重检查的懒加载
在某些情况下可能出现一个类在整个系统的生命周期中都不会被用到。所以我们可以不提前加载,只在第一次使用的时候加载,虽然可能会造成第一次使用时变慢,但是相对预加载的单例牧师来说节省了内存,而懒加载会出现线程并发的问题,所以用双重检查可以避免并发问题,也减小了锁的范围。是一个相对来说比较好的方案。
public class DoubleCheckLazySingleton {
private static volatile DoubleCheckLazySingleton instance= null;
private DoubleCheckLazySingleton(){}
public static DoubleCheckLazySingleton getInstance() {
if (instance==null) {
synchronized (instance) {
instance=new DoubleCheckLazySingleton();
}
}
return instance;
}
}
形式三:基于内部类的懒加载
创内部类的懒加载则是将避免并发问题的方式由加锁同步改成了由jvm类加载机制来保证了
public class InnerClassLazySingleton {
private InnerClassLazySingleton(){}
public static InnerClassLazySingleton getInstance() {
return InnerClass.instance;
}
static class InnerClass {
private static InnerClassLazySingleton instance = new InnerClassLazySingleton();
}
public void print() {
System.out.println("This is InnerClassLazySingleton");
}
}
三、使用场景
- Spring的单例模式就是一个典型使用场景,虽然他是基于3阶段缓存来实现的
- 数据库连接池
- 日志管理器
参考资料
无