Singleton(单例模式)

tech2024-06-17  64

阅读前须知:原文博客请访问 merengues.top

单例模式

单例模式(singleton)保证一个类只有一个实例,并且提供了一个访问全局访问点。

适用性

当类只能有一个实例而且客户可以从一个访问点访问它时。当这个实例应该通过子类化可扩展的,并且客户无须更改代码就能使用拓展的实例。

结构

效果

对唯一实例的受控访问 Singleton可以严格控制用户怎样以及何时访问它。缩小名字空间 Singleton可以避免全局变量污染命名空间。允许对操作和表示的精化 Singleton类可以有子类,可以用所需要类的实例在运行时配置应用。允许可变数目的实例

类别

懒汉式

使用时创建实例。

优点:第一次调用的时候才初始化,避免内存浪费。

缺点:必须加锁才能保证线程安全,加锁则会影响性能。

饿汉式

类加载时就创建实例。

优点:不用加锁就能保证线程安全,执行效率高。

缺点:类加载就初始化,内存浪费。

实现

懒汉式

1)示例1

public class Singleton{ private static Singleton instance; private Singleton(){}; public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }

线程不安全,避免使用。

2)示例2

public class Singleton{ private static Singleton instance; private Singleton(){}; public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }

线程同步,线程安全,效率低,避免使用。

3)示例3

public class Singleton{ private static Singleton instance; private Singleton(){}; public static Singleton getInstance(){ if(instance == null){ synchronized(Singleton.class){ instance = new Singleton(); } } return instance; } }

线程不安全,会产生多个实例,不可用

饿汉式

1)示例1

public class Singleton{ private static Singleton instance = new Singleton; private Singleton(){}; public static Singleton getInstance(){ return instance; } }

2)示例2

public class Singleton{ private static Singleton instance = null; static{ instance = new Singleton; } private Singleton(){}; public static Singleton getInstance(){ return instance; } }

无线程安全问题,影响系统效率,不推荐

双重校验锁
public class Singleton{ private static Singleton instance; private Singleton(){}; public static Singleton getInstance(){ if(instance == null){ synchronized(Singleton.class){ if(instance == null){ instance = new Singleton(); } } } return instance; } }

双重校验锁,线程安全,懒加载,推荐使用

静态内部类
public class Singleton{ private static class SingletonHolder{ private static final Singleton INSTANCE = new Singleton(); } private Singleton(){} public static final Singleton getInstance(){ return SingletonHolder.INSTANCE; } }

静态内部类,线程安全,主动调用才示例化,懒加载效率高,推荐使用

枚举
public enum Singleton{ INSTANCE; private Singleton(){}; public static Singleton getInstance(){ return INSTANCE; } }

枚举类型,无线程安全问题,避免序列化创建新实例,使用少;

注意事项

考虑多线程问题如果类可序列化,考虑反序列化生成多个实例问题,解决方法如下: private Object readResolve() throw ObjectStreamException{ /** *在类中添加readResolve方法返回单例对象 **/ return instance; } 反射会破坏单例模式,避免用反射创建单例对象: private Singleton(){ if(instance != null){ throw new RuntimeException("禁止反射创建单例对象"); } } /** *在类中添加readResolve方法返回单例对象 **/ return instance; } 反射会破坏单例模式,避免用反射创建单例对象: private Singleton(){ if(instance != null){ throw new RuntimeException("禁止反射创建单例对象"); } }
最新回复(0)