单例模式,即保证JVM中最多只会有一个实例化的对象,属于创建型模式。
对于很多场景来说都非常有用,比如有些类的实例化十分复杂、消耗性能,我们只需要初始化一次,以后一直使用这个对象;单例模式有效的减少JVM中不必要对象的生成,降低GC发生。
但是使用单例模式,如果涉及对象内部的全局变量的操作,要注意线程安全问题。
实现方法:私有化构造方法,并提供静态方法获取对象。
饱汉模式
实时加载,如果加载过于复杂,会影响启动效率
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
饿汉模式
锁定整个方法,效率低下
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
double check 饿汉模式
减小锁粒度,但是会遇到万年难得一遇的指令重排序导致的空指针,需要添加volatile
public class Singleton {
// 注意这里需要添加volatile 规避指令重排序导致的npe
private static volatile Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
// 注意这里需要double check null
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
静态内部类模式
利用静态内部类只会加载一次的机制,线程安全,延时加载
public class Singleton {
private static class SingletonInstance {
private static final Singleton instance = new Singleton();
}
private Singleton() {
}
public static synchronized Singleton getInstance() {
return SingletonInstance.instance;
}
}
枚举模式
利用枚举的只能被初始化一次的机制,规避反射和反序列化打破单例模式
public enum Singleton {
INSTANCE;
Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
享元模式和单例模式的区别
单例模式是创建型模式,从自身内部就约束JVM中只能存在一个对象,属于对象本身的属性。
享元模式是结构型模式,侧重对象之间的链接,可以是新对象,也可以是缓存的对象,创建多少与对象本身无关。
网友评论