当前位置: 首页 > news >正文

一、单例模式

一、模式定义:

  • 保证一个类只有一个实例,并且提供一个全局访问点

二、使用场景:

  • 重量级对象,不需要多个实例,如:线程池,数据库连接池

三、类图:

clipboard

四、不同方式创建的单例设计与区别

4.1、懒汉单例模式

  懒汉单例模式的特点是延迟加载,只有在真正使用的时候,才开始实例化,用该方式创建单例对象时,对于线程安全问题和指令重排序导致的初始化并且引用赋值失败的问题,可以用以下2种方式来解决:
①、对于线程安全问题,可以使用【double check】加【锁】进行优化;
②、对于编译器(JIT),CPU可能对指令进行重排序,导致使用尚未初始化的单例实例,因此,需要通过对创建的单例对象添加volatile关键字进行修饰,来防止指令重排序。
懒汉单例模式实现单例的方式,如下所示:

class Service{public static LazySingleton instance = null;public static void main(String[] args) {new Thread(new Runnable() {public void run() {instance = LazySingleton.getInstance();System.out.println(instance);}}).start();new Thread(new Runnable() {public void run() {instance = LazySingleton.getInstance();System.out.println(instance);}}).start();}
}/*** 懒汉式:当第一次去使用Singleton对象的时候才会为其产生实例化对象的操作* */
public class LazySingleton {//volatile关键字可以保证这个对象的赋值顺序按照以下顺序来执行://1、分配空间,2、初始化,3、引用赋值private volatile static LazySingleton instance = null;private LazySingleton() {}/*** 外部调用来获取单例对象的函数*/public static LazySingleton getInstance() {if (instance == null) {synchronized (LazySingleton.class){if (instance == null){instance = new LazySingleton();}}}return instance;}
}

上面代码的运行结果如下:
image

  • volatile关键字可以在字节码层面保证这个对象的赋值顺序按照以下顺序来执行:1、分配空间,2、初始化,3、引用赋值。如果没有volatile关键字,可能在起始初始化的时候,拿到的是空对象。
    clipboard
4.2、饿汉单例模式

  饿汉单例模式的特点是类加载的时候进行初始化,通过JVM的类加载机制来保证单例。饿汉单例模式实现单例的方式,如下所示:

public class HungrySingleton {/*** 在类的内部可以访问私有结构,所以可以在类的内部产生实例化对象*/private static HungrySingleton instance = new HungrySingleton();/*** private 声明构造*/private HungrySingleton() { }/*** 返回对象实例*/public static HungrySingleton getInstance(){return instance;}
}
4.3、静态内部类实现单例

  静态内部类实现单例的特点是只有真正使用对应的类时,才会触发初始化,使用方式包括以下5种:
①、new操作;
②、访问静态属性;
③、访问静态方法;
④、用反射访问类;
⑤、初始化一个类的子类;
静态内部类实现单例的方式,如下所示:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class ServiceInnerClass{public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {//通过反射方式创建InnerClassSingleton实例:Constructor<InnerClassSingleton> declaredConstructor = InnerClassSingleton.class.getDeclaredConstructor();declaredConstructor.setAccessible(true);//因为用private修饰的InnerClassSingleton的构造函数中进行了判断,防止反射方式创建这个对象实例,因此:// ①、反射在加载InnerClassSingleton.class文件前,已经加载了InnerClassSingleton的静态内部类。//②、加载静态内部类时,也加载了静态instance变量,进行初始化。//③、因此,反射方式在创建实例时,会抛出运行时异常。InnerClassSingleton innerClassSingleton = declaredConstructor.newInstance();//只能通过InnerClassSingleton.class的getInstance()函数来获取这个单例InnerClassSingleton instance = InnerClassSingleton.getInstance();}
}class InnerClassSingleton {//4、静态内部类,在加载外部类的时候,该类和该类中的静态变量被加载private static class InnerClassHolder{private static InnerClassSingleton instance = new InnerClassSingleton();}//1、提供private修饰的私有构造方法,保证外部的类无法对该类进行初始化private InnerClassSingleton(){//5、进行判断,防止反射方式创建这个对象实例if(InnerClassHolder.instance != null){throw new RuntimeException("单例模式,不允许多个实例");}}//2、只有在加载这个类的时候,才能拿使用这个静态函数。public static InnerClassSingleton getInstance(){//3、该静态函数内同时加载静态内部类,来初始化InnerClassSingleton对象return InnerClassHolder.instance;}
}
4.4、从序列化文件中读取一个类的实例

从序列化文件中读取一个类的实例实现单例的特点是该实例需要实现Serializable.interface接口,Serializable.interface接口的特点,如下所示:
clipboard
clipboard

从序列化文件中读取一个类的实例来实现单例的方式,如下所示:

import java.io.*;
import java.lang.reflect.InvocationTargetException;class ServiceInnerClass{public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException, ClassNotFoundException {InnerClassSingleton instance = InnerClassSingleton.getInstance();ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("testSerializable"));oos.writeObject(instance);oos.close();//将刚才的对象实例序列化之后,再进行反序列化。得到的实例相同。ObjectInputStream ois = new ObjectInputStream(new FileInputStream("testSerializable"));InnerClassSingleton innerClassSingleton = (InnerClassSingleton) ois.readObject();ois.close();System.out.println(innerClassSingleton == instance);}
}public class InnerClassSingleton implements Serializable {//序列化版本号。不加的话,如果序列化之后,进行修改类中的内容,则不能进行反序列化。private static final long serialVersionUID = 42L;//4、静态内部类,在加载外部类的时候,该类和该类中的静态变量被加载private static class InnerClassHolder{private static InnerClassSingleton instance = new InnerClassSingleton();}//1、提供私有构造方法,保证外部的类无法对该类private InnerClassSingleton(){//5、进行判断,防止反射方式创建这个对象实例if(InnerClassHolder.instance != null){throw new RuntimeException("单例模式,不允许多个实例");}}//2、只有在加载这个类的时候,才能拿使用静态方法。public static InnerClassSingleton getInstance(){//3、同时加载静态内部类,来初始化InnerClassSingleton对象return InnerClassHolder.instance;}private Object readResolve() throws ObjectStreamException {return InnerClassHolder.instance;}}

上面代码的运行结果如下:
image

五、单例模式的应用

  • JDK源码中Runtime.class,使用了饿汉单例模式
    clipboard

  • spring框架中的ReactiveAdapterRegistry.class,使用了懒汉单例模式:
    clipboard
    clipboard

六、JDK源码中,Serializable接口的应用

  • 货币类Currency类
    clipboard
http://www.jsqmd.com/news/358692/

相关文章:

  • 人工智能在智能制造中的应用与未来前景 - 详解
  • 文【牛客tracker 每日一题】
  • 小程序毕设项目推荐-基于微信小程序的温州博物馆系统博物馆展览预约参观讲解基于springboot+小程序的温州博物馆小程序的设计与实现【附源码+文档,调试定制服务】
  • 写论文省心了 8个AI论文工具测评:继续教育毕业论文写作全攻略
  • 计算机小程序毕设实战-基于springboot+小程序的温州博物馆小程序的设计与实现基于Springboot+Uniapp的博物馆预约微信小程序【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 看完就会:降AI率工具,千笔AI VS 知文AI,MBA专属更高效!
  • WPF 自定义控件库名称空间
  • 小程序毕设项目:基于springboot+小程序的温州博物馆小程序的设计与实现(源码+文档,讲解、调试运行,定制等)
  • 导师严选!自考必备的AI论文网站 —— 千笔·专业学术智能体
  • 真心不骗你!本科生专属降AI率网站 千笔·专业降AIGC智能体 VS 锐智 AI
  • 【毕业设计】基于springboot+小程序的温州博物馆小程序的设计与实现(源码+文档+远程调试,全bao定制等)
  • 毕业论文无忧:11个AI辅助写作网站精选
  • AI元人文:跨文化共生与文明新契约
  • 小程序计算机毕设之基于springboot+小程序的温州博物馆小程序基于微信小程序的温州博物馆系统博物馆展览预约参观讲解(完整前后端代码+说明文档+LW,调试定制等)
  • AI赋能论文写作:11款跨学科工具推荐
  • 【计算机毕业设计案例】基于Springboot+Uniapp的博物馆预约微信小程序设计与实现基于springboot+小程序的温州博物馆小程序的设计与实现(程序+文档+讲解+定制)
  • 学术研究利器:11款AI论文写作工具盘点
  • 人工智能驱动的科研新范式及学科应用研究
  • 科研效率拉满!2026 优质 AI 写论文软件精选(实测推荐)
  • 大模型提示词:零样本(Zero-shot)和少样本(Few-shot)介绍(Zero shot、Few shot)
  • 高效论文写作:11个AI工具助力学术研究
  • 多学科适用:11个AI辅助毕业论文写作平台
  • [全流程详细教程]Docker部署ClawBot, 使用GLM4.7, 接入TG Bot实现私人助理. 解决Docker Openclaw Permission Denied问题
  • php python+vue开题报告基于Android平台的相册管理系统
  • 汽车电动充气泵方案电路设计
  • 计算机毕业设计springboot学生作业管理系统 基于Spring Boot的在线作业提交与评阅平台 高校课程作业数字化管理平台的设计与实现
  • php python+vue商品管理系统开题报告文献综述
  • 计算机毕业设计springboot音乐推荐系统 基于协同过滤算法的个性化音乐推送平台开发 Spring Boot驱动的智能化歌曲推荐服务平台构建
  • GPS定位方案与HC32L130MCU应用全解析
  • php python+vue大学校排课管理信息系统设计开题报告