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

什么是单例模式,有哪些应用?

目录

一、定义

二、应用场景

三、6种实现方式

1、懒汉式,线程不安全。

2、懒汉式,线程安全

3、双检锁/双重校验锁(DCL,即 double-checked locking)

4、静态内部类方式-------只适用于静态域

5、饿汉式

6、枚举

四、总结


一、定义

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

单例模式涉及到一个单一的类,单例类只能自己创建唯一的一个实例,并提供了一个全局访问点使所有其他对象获取到类的唯一实例。

特点:

  • 唯一实例:确保类只有一个实例。
  • 全局访问点:提供一个全局访问点来获取类的实例。
  • 线程安全:在多线程环境中,确保实例的唯一性。

二、应用场景

1、配置管理:应用程序可能需要一个只初始化一次的配置管理器。

2、日志记录:日志记录器通常只需要一个实例,以避免日志信息的混乱。

3、性能优化:某些对象的创建成本很高,使用单例模式可以避免重复创建。

三、6种实现方式

分类:

  • 饿汉式:类加载就会导致该单实例对象被创建。
  • ​懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建。
1、懒汉式,线程不安全。

在这种情况下,我们只有调用 getInstance 方法, instance 对象才会被创建。

在多线程情况下,很多线程都来请求获取该对象,这样就可能创建出多个对象,导致线程不安全。

/*** 懒汉式  线程不安全*/
public class SingletonLazy {//定义一个私有构造方法private SingletonLazy(){}//创建该类对象private static SingletonLazy instance;//对外提供静态方法获取该对象public static SingletonLazy getInstance(){if(instance==null){instance = new SingletonLazy();}return instance;}
}
2、懒汉式,线程安全

由于上述会出现线程不安全问题,所以我们通过加同步锁,保证每次只有一个线程可以对当前对象进行操作,确保了线程安全。但加锁会影响效率。

/*** 懒汉式  线程安全*/
public class SingletonLazy {//定义一个私有构造方法private SingletonLazy(){}//创建该类对象private static SingletonLazy instance;//对外提供静态方法获取该对象 , 加锁public static synchronized SingletonLazy getInstance(){if(instance==null){instance = new SingletonLazy();}return instance;}
}
3、双检锁/双重校验锁(DCL,即 double-checked locking)

我们使用 volatile 关键字, volatile 关键字可以保证可见性和有序性,这个关键字禁止了对当前修饰的变量上下文重排序。保证了方法的可靠性。采用双锁机制,安全且在多线程情况下能保持高性能。

进行二次判断的原因:

假设有两个线程a,b,他们都去请求我们单例模式下类的实例,当第一个判断的时候,两个线程都会进入判断代码块中进行锁的抢占,最终a抢占到了锁,那么b只能在加锁的代码块外部进行等候。这个时候a创建了对象的实例,完成功能后归还了锁,这个时候线程b马上抢占到了锁,然后进入内部代码块。假如没有第二次判断的话,线程a就会再次创建一个新的对象,导致线程不安全。所以,要在这里再加一次判断。

/*** 懒汉式  双重校验锁*/
public class SingletonLazy {//定义一个私有构造方法private SingletonLazy(){}//创建该类对象private volatile static SingletonLazy instance;//对外提供静态方法获取该对象 , 加双重锁public static SingletonLazy getInstance(){if(instance==null){synchronized (instance.getClass()){if(instance == null){instance = new SingletonLazy();}}}return instance;}
}
4、静态内部类方式-------只适用于静态域

静态内部类单例模式中实例由内部类创建,由于 JVM 在加载外部类的过程中, 是不会加载静态内部类的,只有内部类的属性/方法被调用时才会被加载,并初始化其静态属性。静态属性由于被 static 修饰,保证只被实例化一次,并且严格保证实例化顺序。

/*** 静态内部类方式*/
public class SingletonLazy {//私有构造方法private SingletonLazy() {}//定义静态类private static class SingletonHolder {//静态方法private static final SingletonLazy INSTANCE = new SingletonLazy();}//对外提供静态方法获取该对象public static SingletonLazy getInstance() {return SingletonHolder.INSTANCE;}
}
5、饿汉式

它基于 classloader 机制避免了多线程的同步问题,instance 在类装载时就实例化。

/*** 饿汉式*/
public class SingletonEhan {//私有构造方法private SingletonEhan(){}//创建并实例化该类对象private static SingletonEhan instance = new SingletonEhan();//对外提供静态方法获取该对象public static SingletonEhan getInstance(){return instance;}
}
6、枚举

这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。

public enum Singleton {  INSTANCE;  public void whateverMethod() {  }  
}

四、总结

一般情况下,使用第5种饿汉式。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 模板、STL 简介(深度剖析)
  • VisualRules-Web案例展示(一)
  • mysql、oracle、db2数据库连接参数
  • SpringSecurity通用权限管理系统
  • 关于合芯新通RTK配置的方法记录7.23
  • k8s部署rabbitmq集群
  • Json结构解析比较
  • 69、ncnn学习onnx2ncnn不支持带三维算子相乘gemm/repeat转换方法学习
  • CH04_依赖项属性
  • day02 mybatis
  • 微信小程序数组绑定使用案例(二)
  • 《流程引擎原理与实践》开源电子书
  • 【大数据专题】数据仓库
  • 从零开始手写STL库:List
  • Huawei、Cisco 路由中 RIP 协议 summary 的用法
  • 网络传输文件的问题
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • 「译」Node.js Streams 基础
  • iOS 系统授权开发
  • jdbc就是这么简单
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • PHP CLI应用的调试原理
  • React+TypeScript入门
  • 动态规划入门(以爬楼梯为例)
  • 记录:CentOS7.2配置LNMP环境记录
  • 聊聊flink的BlobWriter
  • 浏览器缓存机制分析
  • 前端之React实战:创建跨平台的项目架构
  • 思否第一天
  • NLPIR智能语义技术让大数据挖掘更简单
  • 翻译 | The Principles of OOD 面向对象设计原则
  • 数据库巡检项
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • (145)光线追踪距离场柔和阴影
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (翻译)terry crowley: 写给程序员
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (回溯) LeetCode 40. 组合总和II
  • (几何:六边形面积)编写程序,提示用户输入六边形的边长,然后显示它的面积。
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .NET Micro Framework 4.2 beta 源码探析
  • .NET MVC第三章、三种传值方式
  • .NET 读取 JSON格式的数据
  • .net 发送邮件
  • .net 提取注释生成API文档 帮助文档
  • .netcore如何运行环境安装到Linux服务器
  • .net对接阿里云CSB服务
  • .NET中的十进制浮点类型,徐汇区网站设计
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • @AutoConfigurationPackage的使用
  • @ConditionalOnProperty注解使用说明
  • @Data注解的作用
  • @NoArgsConstructor和@AllArgsConstructor,@Builder