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

Javaee:单例模式

文章目录

  • 单例模式
  • 单例模式的使用场景
  • 单例模式的实现方式
    • 饿汉模式(急)
      • 实现方式
    • 懒汉模式(缓)
      • 使用静态内部类创建单例模式(推荐)
  • 总结

单例模式

保证一个类只能创建一个实例,不能创建多个实例

单例模式的使用场景

如果频繁的创建和销毁对象的开销非常大,并且这些类的对象可以复用,势必会造成资源浪费,性能低和资源利用率低

举例:数据库连接池
访问数据库,需要创建数据库链接对象,创建数据库链接对象和销毁的开销是非常大的,而数据库连接池会采用单例模式,只实例一个对象来确保连接池的唯一性和全局可访问性,也就很好的提高资源利用率

好处

  1. 通过重用连接池中的连接,避免了频繁地创建和销毁数据库连接,从而节省了系统资源。
  2. 可以更容易地管理和监控连接池的状态和性能。

线程池中也应用了单例模式的设计模式

单例模式的实现方式

饿汉模式(急)

在类加载的同时创建实例

实现方式

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

由于在类加载的过程就创建了实例,不涉及线程安全问题

重点:

  1. 使用private修饰构造方法——不能通过new直接创建对象
  2. 使用static修饰对象——类加载就创建好对象
  3. 通过调用getInstance——获得实例对象

优点

类加载就创建实例,只涉及到读操作,天生线程安全
没有加锁,可以直接使用,减少延迟

缺点

无论是否需要使用都会在类加载时创建,可能会导致资源浪费
若是重启服务,无法实现延迟加载的特性,会拖慢运行速度

懒汉模式(缓)

只有在真正需要时才创建实例

单线程版本

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

只有在真正需要时才创建实例——懒

举例:

妈妈叫我去小卖部买酱油,而我在看电视,此时我的做法是不听妈妈的话,继续看电视,等到妈妈要生气了我才去买

不难发现上述代码是线程不安全的,在多个线程下,很有可能会越过判断语句,直接去创建对象

改进

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

加锁,在构建对象的时候才需要考虑同步,所以我们对于new对象的操作进行加锁,上述代码中getInstance是读操作,不存在锁竞争,所有线程都能访问,而第二步的判断,如果没有实例创建,所有的线程就会去竞争锁,抢到锁的线程创建好实例,以后的getInstance操作都是直接返回当前实例对象。

但是有个问题,如果同时有两个线程进入了if语句,其中一个线程拿到锁创建实例之后将锁释放了,此时另一个线程也能创建实例——不符合要求,线程不安全

解决方案:双重检锁

使用if语句检查当前实例是否已经被创建

还要注意内存可见性问题

instance = new SingletionLazy();	

对应三条指令

  1. 给对象分配内存
  2. 初始化对象
  3. 返回对象指向的内存地址

编译器在逻辑不改变的情况会自动优化,进行指令重排序

解决方案:volatile关键字

优化版本

class SingletionLazy {private static volatile SingletionLazy instance = null;private static Object locker = new Object();public static SingletionLazy getInstance() {if (instance == null) {//判断实例是否已经创建synchronized (locker) {if (instance == null) {//判断是否需要new对象instance = new SingletionLazy();}}}return instance;}
}

优点

真正需要创建实例的时候,先判断是否为空,如果为空,再创建单例对象
真正需要用到的时候创建减少了不必要的开销

使用静态内部类创建单例模式(推荐)

这种方式是线程安全的,不需要额外的同步(不用加锁)

public class Singleton {  // 私有构造函数  private Singleton() {  // 初始化代码  }  // 静态内部类,负责持有单例实例  private static class SingletonHelper {  private static final Singleton INSTANCE = new Singleton();  }  // 获取单例实例的公共静态方法  public static Singleton getInstance() {  return SingletonHelper.INSTANCE;  }  public static void main(String[] args) {  Singleton singleton = Singleton.getInstance();    }  
}

总结

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。有多种实现方式,懒汉模式需要注意线程安全问题。


http://www.mrgr.cn/news/61325.html

相关文章:

  • LabVIEW数据库管理系统
  • 第 5 场 算法季度赛
  • 从github上,下载的android项目,从0-1进行编译运行-踩坑精力,如何进行部署
  • 【update 更新数据语法合集】.NET开源ORM框架 SqlSugar 系列
  • 网络安全 | Web安全常见漏洞和防护经验策略
  • 实现nacos配置修改后无需重启服务--使用@RefreshScope注解
  • linux 查看磁盘和内存的使用情况
  • 大模型提示词简介 举例
  • VBA技术资料MF221:删除给定工作簿的指定模块
  • Java-I/O框架06:常见字符编码、字符流抽象类
  • 论文学习 | 《锂离子电池健康状态估计及剩余寿命预测研究》
  • DBeaver如何导出insert的sql数据
  • 配合数据库进行网页的动态数据上传
  • 四款图片编辑软件,P图更轻松
  • 芯片固件加密方式
  • 晓羽扫码点餐快销版系统源码
  • 简易SQL注入原理及注入失败原因
  • k8s 二进制部署安装(三)
  • 玉石渲染用什么渲染软件最好?单品渲染用哪个软件?
  • Mask RCNN原理详解(个人学习笔记)
  • 河南洛宁200MW/400MWh电化学储能示范项目招标公告
  • 【机器学习】14. 集成学习 ensemble: bagging, boosting, 随机森林 random forest
  • Springboot自动装配原理
  • C#自定义事件的案例
  • XD6500S替代翱捷ASR6500S系列低功耗lora SPI模块SX1262/SX1278
  • Spring之HTTP客户端--RestTemplate的使用