为什么使用单例模式:
在开发中如果频繁的实例化对象会很占用内存,会导致内存溢出,所以最好根据需求尽量少实例化对象,使用单例模式可以确保只有一个实例会被创建。单例模式也给了我们一个全局的访问点,和全局变量一样方便,又没有全局变量的缺点
经典的单例模式
懒汉子模式:懒汉子模式线程安全但是当进行垃圾回收被回收掉的时候就会出空指针异常
public class SingletonTest {
// 定义一个私有的构造方法
private SingletonTest() {
}
// 将自身的实例对象设置为一个属性,并加上Static和final修饰符
private static final SingletonTest instance = new SingletonTest();
// 静态方法返回该类的实例
public static SingletonTest getInstance() {
return instance;
}
}
饱汉子模式:非线程安全,多线程高并发的时候会创建很多实例
public class SingletonTest {
private SingletonTest() {
}
private static SingletonTest instance;
public static SingletonTest getInstance() {
if (instance == null)
instance = new SingletonTest();
return instance;
}
}
安全锁模式:保证线程安全
public class SingletonTest {
private SingletonTest() {
}
private static SingletonTest instance;
public static SingletonTest getIstance() {
if (instance == null) {
synchronized (SingletonTest.class) {
if (instance == null) {
instance = new SingletonTest();
}
}
}
return instance;
}
}
好了,秀技术的时候了
静态内部类式
// 静态内部类式
// 这样不使用这个内部类SingletonHolder
// 那么jvm虚拟机他就不会去加载这个类
public class Singleton4 {
private static class SingletonHolder {
private static final Singleton4 INSTANCE = new Singleton4();
}
private Singleton4() {
}
public static Singleton4 getInstance() {
return SingletonHolder.INSTANCE;
}
}
枚举式
// 枚举式
// 比较推荐的写法,可以应对多次序列化和反射攻击
public enum Singleton5 {
INSTANCE;
public static Singleton5 getInstance() {
return INSTANCE;
}
}
序号 | 名称 | 优点 | 缺点 |
1 | 懒汉式 | 简单 | 线程不安全,存在反序列化攻击和反射攻击 |
2 | 饿汉式 | 简单 | 没有延迟加载,有可能浪费空间,存在反序列化攻击和反射攻击 |
3 | 安全锁模式 | 线程安全 | 写法复杂,存在反序列化攻击和反射攻击 |
4 | 静态内部类式 | 比双检索简单 | 存在反序列化攻击和反射攻击 |
5 | 枚举式 | 简单、线程安全、可以防止反序列化攻击和反射攻击 | / |
为什么可以防止反序列化攻击和反射攻击:因为内部类和枚举不能通过反射机制进行生成类或者反射调用