Java单例模式Singleton及其七种实现方式
2022/1/3 22:08:55
本文主要是介绍Java单例模式Singleton及其七种实现方式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
什么是单例模式
简述
单例模式(Singleton Pattern)是创建型设计模式中最简单且应用最为广泛的设计模式之一,单例模式属于创建型模式,提供了一种对象创建的思路。
使用单例模式时,目标类被要求确保有且仅有一个实例,对于系统任一对目标类的访问,不需要单独实例化类,只需要访问由目标类负责创建的唯一对象实例即可。
特点
- 使用单例模式的目标类仅有一个实例
- 由目标类自行创建管理唯一实例
- 目标类对外提供实例访问方法
应用场景
出现以下场景,可以考虑使用单例模式
- 某类实例需要被频繁的创建,使用后需要频繁销毁
- 某类实例化耗时长、占用资源多且使用频繁
- 某类实例频繁的与数据库或文件交互
- 某类包含全局状态字段,或在业务逻辑上仅应有单一实例
优缺点
使用单例模式的优点:
- 减少开销,因为内存中仅有一个实例,减少内存开销,又因为不需要频繁实例化类,减少了性能(时间)开销。
- 避免对某资源的多重占用,例如对某些文件执行写操作时,单例可以保证对文件同时只有一个写操作。
- 目标类对外提供唯一实例访问方法,实例可以作为共享资源的被访问。
- 在某些场景下,某类在逻辑上仅应存在单一实例,使用单例模式可以帮助实现。
单例模式的不足:
- 违背开闭原则(即对扩展开放,对修改封闭),想要对类进行扩展时,通常只能修改代码。
- 易违背单一职责原则,即某一功能全部写在一个类中,容易变得冗杂。
单例模式的七种实现方式
懒汉式单例
顾名思义,此种方式实现的单例模式是在目标类要被使用时才创建实例,这种懒加载的好处是在目标类未被实际使用时,不会有实例占据内存空间。
线程不安全方式
此种实现方式线程不安全,在目标类实例还未被创建时,如果有两个线程同时访问了getInstance(),容易产生多个实例,破坏实例的唯一性,不推荐使用。
public class Singleton { public static Singleton instance; // 使用私有构造方法以避免被外部实例化 确保单例 private Singleton(){} public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
线程安全方式
针对前一种线程不安全的实现方式,可以使用synchronized关键字修饰方法,确保方法同时只能被一个线程访问。虽然此种方式可以保证线程安全同时实现单例,但在单例被创建后,synchronized便失去了本场景下的作用(确保实例的唯一性),且会降低性能开销
public class Singleton { public static Singleton instance; // 使用私有构造方法以避免被外部实例化 确保单例 private Singleton(){} //使用synchronized保证线程安全 public synchronized static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
DCL双重检查锁定
前文提及懒汉式为保证线程安全引入synchronized导致性能开销提升,由此衍生出了双重检查锁定(Double Check Lock)的单例实现方式,使用volatile关键字保证可见性避免JVM指令重排引发的问题,同时使用synchronized保证实例创建过程唯一,既保证了懒加载的线程安全,又相较synchronized修饰方法减少了性能开销。
public class DCLSingleton { // 注意instance必须要由volatile关键字修饰 目的是保证instance变量的可见性 避免由于指令重排破坏单例的唯一性 private static volatile DCLSingleton instance; private DCLSingleton() {} public static DCLSingleton getInstance() { if(instance == null) { //首先判断是否实例化 //使用synchronized加锁保证实例创建唯一 synchronized (DCLSingleton.class) { if(instance == null) { instance = new DCLSingleton(); } } } return instance; } }
饿汉式单例
饿汉式单例的思路是利用static关键字,使目标类在类加载阶段就创建唯一实例,保证实例在被访问前就已经被创建,确保唯一性,线程安全。
静态变量
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(){} static{ instance = new Singleton(); } public static Singleton getInstance(){ return instance; } }
静态内部类
在外部类被装载时,静态内部类不会跟着一起被装载,而是在静态内部类实际被使用的时候(getInstance被调用)才会装载并实例化,所以使用静态内部类实现单例模式具有懒加载的优点,同时JVM在装载类的过程中可以保证线程安全。
public class SingletonStaticClass { private SingletonStaticClass(){} public static final SingletonStaticClass getInstance(){ return SingletonInstance.instance; } private static class SingletonInstance{ private static final SingletonStaticClass instance = new SingletonStaticClass(); } }
枚举
枚举实现单例是最安全且写法最简单的,JVM会保证枚举类不能被反射且构造器只能被调用一次,彻底解决了其他单例模式容易被反射和序列化反序列化攻击的问题(见下文),推荐使用。
枚举类单例
public enum EnumSingleton { INSTANCE; public void method() { System.out.println("doSomething"); } }
已有类改造
public class EnumSingletonEnhance { private EnumSingletonEnhance(){} public enum SingletonEnum { SINGLETON_ENUM; private EnumSingletonEnhance instance = null; private SingletonEnum(){ instance = new EnumSingletonEnhance(); } public EnumSingletonEnhance getinstance(){ return instance; } } }
这篇关于Java单例模式Singleton及其七种实现方式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-01后台管理开发学习:新手入门指南
- 2024-11-01后台管理系统开发学习:新手入门教程
- 2024-11-01后台开发学习:从入门到实践的简单教程
- 2024-11-01后台综合解决方案学习:从入门到初级实战教程
- 2024-11-01接口模块封装学习入门教程
- 2024-11-01请求动作封装学习:新手入门教程
- 2024-11-01登录鉴权入门:新手必读指南
- 2024-11-01动态面包屑入门:轻松掌握导航设计技巧
- 2024-11-01动态权限入门:新手必读指南
- 2024-11-01动态主题处理入门:新手必读指南