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

目录

一、定义

二、应用场景

三、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种饿汉式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/48413.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式C++、STM32、树莓派4B、OpenCV、TensorFlow/Keras深度学习:基于边缘计算的实时异常行为识别

1. 项目概述 随着物联网和人工智能技术的发展,智能家居安全系统越来越受到人们的关注。本项目旨在设计并实现一套基于边缘计算的智能家居安全系统,利用STM32微控制器和树莓派等边缘设备,实时分析摄像头数据,识别异常行为(如入侵、跌倒等),并及时发出警报,提高家庭安全性。 系…

英福康INFICON RGAs for the AMAT Endura 5500 课件PPT

英福康INFICON RGAs for the AMAT Endura 5500 课件PPT

uniapp+vue3实现音乐播放器,包含上一首、下一首、暂停、播放、下载音频、下载视频、进度条拖拽、歌词等

uni-app中实现音乐播放器 1、主要利用的是uni-app中提供的uni.createInnerAudioContext()来进行实现&#xff1b; 2、代码示例 &#xff08;1&#xff09;主页面代码展示 <template><view class"songDetailContainer"><view class"bg&quo…

记录uni-app横屏项目:自定义弹出框

目录 前言&#xff1a; 正文&#xff1a; 前言&#xff1a;横屏的尺寸问题 最近使用了uniapp写了一个横屏的微信小程序和H5的项目&#xff0c;也是本人首次写的横屏项目&#xff0c;多少是有点踩坑不太适应。。。 先说最让我一脸懵的点&#xff0c;尺寸大小&#xff0c;下面一…

vxe-弹窗初始化激活选中Vxe-Table表格中第一行input输入框

1.实现效果 2.Modal弹窗的渲染过程 一、Vue组件的生命周期 Vue组件从创建到销毁会经历一系列的生命周期钩子&#xff0c;这些钩子为开发者提供了在不同阶段插入自定义逻辑的机会。在Modal弹窗的上下文中&#xff0c;这些生命周期钩子同样适用。 beforeCreate&#xff1a;组件…

简化Android数据管理:深入探索SQLite数据库

SQLite数据库在Android中的使用 SQLite是一种精巧的、轻量级的、无服务器的、零配置的、事务性SQL数据库引擎。相较于其他数据库系统&#xff0c;SQLite更适用于需要轻量级解决方案的移动应用场景。本文将详细介绍SQLite数据库在Android中的使用&#xff0c;包括数据库的创建、…

【大模型基础】4.1 数据挖掘(待)

一、什么是文本挖掘? 文本挖掘指的是从文本数据中获取有价值的信息和知识,它是数据挖掘中的一种方法。文本挖掘中最重要最基本的应用是实现文本的分类和聚类,前者是有监督的挖掘算法,后者是无监督的挖掘算法。 二、文本挖掘的作用是什么? 能够从文本数据中获取有价值的…

数据仓库中的数据治理

一、数据治理的定义&#xff1a; 数据治理是一套用于管理和保护数据资源的规范、流程和控制机制。在数据仓库中&#xff0c;数据治理涉及规划、定义、监控和维护数据的标准、策略和流程&#xff0c;以确保数据的质量、完整性和一致性。 二、数据治理的流程&#xff1a; 制定数…

设计模式实战:在线购物系统的设计与实现

简介 本篇文章将介绍如何设计一个在线购物系统&#xff0c;系统包括购物车、订单处理、支付等功能。我们将通过这一项目&#xff0c;应用组合模式、命令模式、策略模式和观察者模式来解决具体的设计问题。 问题描述 设计一个在线购物系统&#xff0c;用户可以浏览商品、将商…

Qt中的高分辨率及缩放处理

写在前面 使用Qt开发界面客户端&#xff0c;需要考虑不同分辨率及缩放对UI界面的影响&#xff0c;否则会影响整体的交互使用。 问题 高分辨率/缩放设备上图片/图标模糊 若不考虑高分辨及缩放处理&#xff0c;在高分辨率/缩放设备上&#xff0c;软件中的图片、图标可能会出现…

【数据治理】隐私计算:数据治理中的安全守护者

隐私计算&#xff1a;数据治理中的安全守护者 引言一、隐私计算概述二、隐私计算的关键技术及其核心与业务逻辑三、隐私计算在数据治理中的应用案例四、隐私计算面临的挑战与未来发展五、结论 引言 数据治理是现代企业运营的关键组成部分&#xff0c;特别是在数据安全和隐私保…

调试DM9000过程中出现的认知与逻辑问题

在单片机项目中&#xff0c;很多难解的、涉及到硬件的bug&#xff0c;往往会采用对比实验的方式&#xff0c;即正常板子和异常板子跑同一份代码来对比现象。 这里有一个很重要的认知前提&#xff0c;就是这份代码不一定没有问题&#xff0c;只能说这份代码放在正常的硬件上没有…

解决jupyter argparse报错

jupyter argparse报错 文章目录 一、jupyter argparse报错 一、jupyter argparse报错 args parser.parse_args()这行代码改为&#xff1a; args parser.parse_args(args[])完整的代码为&#xff1a; import argparseparser argparse.ArgumentParser() parser.add_argumen…

力扣题解(零钱兑换II)

518. 零钱兑换 II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 3…

sourcetree中常用功能使用方法及gitlab冲突解决

添加至缓存&#xff1a;等于git add 提交&#xff1a;等于git commit 拉取/获取&#xff1a;等于git pull ,在每次要新增代码或者提交代码前需要先拉取一遍服务器中最新的代码&#xff0c;防止服务器有其他人更新了代码&#xff0c;但我们自己本地的代码在我们更新前跟服务器不…

Java实战中如何使用多线程(线程池)及其为什么使用?

这个话题在入行之前就想过很多次&#xff0c;很多8古文或者你搜索的结果都是告诉你什么提高高并发或者是一些很高大上的话&#xff0c;既没有案例也没有什么公式去证明&#xff0c;但是面试中总是被问到&#xff0c;也没有实战经历&#xff0c;所以面试时一问到多线程的东西就无…

JAVA零基础小白自学日志——第十九天

文章目录 1.private&#xff08;私有&#xff09;2.static&#xff08;静态&#xff09;3.final&#xff08;最终&#xff09;[1].fianl修饰变量[2].fianl修饰方法[3].fianl修饰类[4].为什么需要fianl关键字修饰类和方法 4.private\static\final的共同点5.同名变量6.方法重载和…

深度学习入门——与学习相关的技巧

前言 本章将介绍神经网络的学习中的一些重要观点&#xff0c;主题涉及寻找最优权重参数的最优化方法、权重参数的初始值、超参数的设定方法等 此外&#xff0c;为了应对过拟合&#xff0c;本章还将介绍权值衰减、Dropout等正则化方法&#xff0c;并进行实现。 最后将对近年来…

细说MCU用单路DAC模块设计和输出锯齿波的实现方法

目录 一、STM32G474RE的DAC模块 二、配置 1.配置DAC 2.选择时钟源和Debug 3.配置系统时钟 三、代码修改 1.启动DAC 2.给DAC的数据输出寄存器赋值 3.运行并观察输出 一、STM32G474RE的DAC模块 有些MCU本身就带有数/模转换器(Digital to Analog Converter,DAC)模块&am…

昇思25天学习打卡营第20天|Diffusion扩散模型

Mindspore框架利用扩散模型DDPM生成高分辨率图像&#xff08;生成高保真图像项目实践&#xff09; Mindspore框架利用扩散模型DDPM生成高分辨率图像|&#xff08;一&#xff09;关于denoising diffusion probabilistic model &#xff08;DDPM&#xff09;模型Mindspore框架利…