设计模式—单例模式
懒汉式 — 延迟加载
类会被立刻初始化的五种情况:
假设现在有一个A.class
1. A类型实例被创建
2. A类中声明的一个静态方法被调用
3. A类中声明的一个静态成员被赋值
4. A类中声明的一个静态成员被使用并且该成员不是常量成员
5. A类如果是个顶级类,并且类中有嵌套的断言语句
双重检验模式
import java.io.Serializable;
/**
* @date 2021/3/18 14:28
*/
public class LazySingleton implements Serializable {
//volatile 防止类实例化阶段的指令重排序
//注:类初始化重排序问题:
// 1:分配内存空间 2:调用构造函数初始化成员变量 3:将变量指向分配的内存空间地址
//执行顺序可能为 1->2->3 或者 1->3->2
//volatile可以禁止指令重排序
private volatile static LazySingleton lazySingleton = null;
private LazySingleton() {
//防止反射调用构造方法进行对象实例化,不能根本性拦截,因为反射可以改变flag值
if (flag) {
flag = false;
} else {
throw new RuntimeException("禁止反射调用对象实例化");
}
}
public static LazySingleton getInstance() {
if (lazySingleton == null) {
synchronized (LazySingleton.class) {
if (lazySingleton == null) {
lazySingleton = new LazySingleton();
}
}
}
return lazySingleton;
}
//当对象被序列化后,在进行反序列化获取时会重新生成一个新的对象
// readResolve方法再反序列化时被调用返回我们指定要反悔的单例对象
private Object readResolve () {
return lazySingleton;
}
}
静态内部类模式
/**
* @date 2021/3/18 14:35
*/
public class StaticClassSingleton {
private StaticClassSingleton () {
}
public static class StaticClassSingletonHolder {
//类被加载时初始化对象,不存在多线程问题,父类被加载是该子类并不会被加载,也实现了延迟加载的功能
private static StaticClassSingleton staticClassSingleton = new StaticClassSingleton();
}
public static StaticClassSingleton getInstance() {
return StaticClassSingletonHolder.staticClassSingleton;
}
}
饿汉式
/**
* @date 2021/3/18 14:34
*/
public class HungerSingleton {
//类被加载时初始化对象,不存在多线程问题
private final static HungerSingleton hungerSingleton = new HungerSingleton();
private HungerSingleton () {
}
public static HungerSingleton getInstance() {
return hungerSingleton;
}
}
枚举方式
/**
* @date 2021/3/18 14:43
枚举方式可以方式反射及序列化对单例模式的破坏
*/
public enum EnumSingleton {
INSTANCE {
@Override
protected Singleton getInstance() {
if (data == null) {
synchronized (EnumSingleton.class) {
if (data == null) {
data = new Singleton();
}
}
}
return data;
}
};
protected abstract Singleton getInstance();
private volatile static Singleton data;
private static class Singleton {
}
}
测试类
/**
* @author wwy
* @date 2021/3/18 14:38
*/
public class Test {
public static void main1(String[] args) {
Object instance11 = LazySingleton.getInstance();
Object instance12 = LazySingleton.getInstance();
System.out.println(instance11);
System.out.println(instance12);
System.out.println(instance11 == instance12);
}
public static void main2(String[] args) {
Object instance21 = HungerSingleton.getInstance();
Object instance22 = HungerSingleton.getInstance();
System.out.println(instance21);
System.out.println(instance22);
System.out.println(instance21 == instance22);
}
public static void main3(String[] args) {
Object instance31 = StaticClassSingleton.StaticClassSingletonHolder.getInstance();
Object instance32 = StaticClassSingleton.StaticClassSingletonHolder.getInstance();
System.out.println(instance31);
System.out.println(instance32);
System.out.println(instance31 == instance32);
}
public static void main4(String[] args) {
Object instance41 = EnumSingleton.INSTANCE.getInstance();
Object instance42 = EnumSingleton.INSTANCE.getInstance();
System.out.println(instance41);
System.out.println(instance42);
System.out.println(instance41 == instance42);
}
}
序列化问题验证
import java.io.*;
/**
* @author wwy
* @date 2021/3/18 11:06
*/
public class Test {
public static void main(String[] args) throws Exception {
HungrySingleton instance = HungrySingleton.getInstance();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
oos.writeObject(instance);
File file = new File("singleton_file");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
HungrySingleton newInstance = (HungrySingleton) ois.readObject();
System.out.println(instance);
System.out.println(newInstance);
System.out.println(instance == newInstance);
}
private static class HungrySingleton implements Serializable{
private final static HungrySingleton hungrySingleton = new HungrySingleton();
public static HungrySingleton getInstance() {
return hungrySingleton;
}
}
}