单例模式(Singleton)是一种创建对象的设计模式,确保在应用程序中只有一个实例。
优点:
1、确保一个类只有一个实例,避免了重复创建对象的开销。
2、提供全局访问点,方便在整个程序中访问该实例。
3、可以控制对象的数量和生命周期,确保对象的一致性和可靠性。
4、可以避免多线程冲突问题,在多线程环境下保证对象的唯一性。
缺点:
1、单例模式可能导致紧耦合,使得程序的扩展性和可维护性变差。
2、单例模式不适合需要多个相互独立的实例的情况,违背了单一职责原则。
3、单例模式的实现需要考虑线程安全,增加了实现的复杂性。
五种实现方式:
饿汉式:没有实现懒加载,在类加载时初始化,即在运行之前只是将打包的代码加载到内存的时候就初始化,会造成内存浪费,但是它线程安全,并且执行效率高。
1 2 3 4 5 6 7 8 9 10 11
| public class Singleton {
private static final Singleton singleton = new Singleton();
private Singleton() {}
public static Singleton getInstance() { return singleton; } }
|
懒汉式:单例对象被使用的时候才初始化,避免了内存浪费。占用空间小,效率有问题,线程不安全。
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Singleton{ private static Singleton singleton; private Singleton() { } public static Singleton getInstance() { if(singleton == null) { singleton = new Singleton(); } return singleton; } }
|
当多个对象进入getInstance()方法中的if时被判断为空,可能创建多个实例对象。
解决办法:
可以在方法上加上synchronized同步锁,但是运行效率低下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Singleton { private static Singleton singleton; private Singleton() {} public static synchronized Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return instance; } }
|
双重检查锁:提高了同步锁的效率,使用双重检查锁进一步进行优化,可以避免整个方法被锁,只对需要锁的代码部分进行加锁,可以提高执行效率。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Singleton { private static volatile Singleton singleton; private Singleton() {} public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return instance; } }
|
静态内部类:引入一个静态内部类,静态内部类只有在调用的时候才会加载,保证了Singleton实例的延迟初始化,又保证了实例的唯一性。
静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时吗,默认的方式运行得到的结果就是多例的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Singleton { private Singleton() { } private static class InnerObject { private static Singleton singleton = new Singleton(); } public static synchronized Singleton getInstance() { return InnerObject.singleton; } }
|
内部枚举类:防止了反射和序列化攻击。通过Java反射机制可以实例化构造方法为private的类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class SingletonFactory { private enum EnumSingleton { SINGLETON; private Singleton singleton; private EnumSingleton() { singleton = new Singleton(); }
public Singleton getInstance() { return singleton; } }
public static Singleton getInstance() { return EnumSingleton.SINGLETON.getInstance(); } }
class Singleton{ public Singleton() { } }
|