设计模式之单例

news2024/11/18 8:12:59

文章目录

  • 前言
  • 一、单例模式的基本定义
  • 二、懒汉式单例
  • 三、饿汉式单例
  • 四、懒汉式单例存在的线程安全问题
  • 总结


前言

单例模式是比较经典的设计模式,本篇我们将结合实际案例说明单例模式的实现原理,以及存在的问题。


一、单例模式的基本定义

单例模式(Singleton Pattern)确保某一个类只有一个实例方法,而且自行实例化并向整个系统提供这个实例,这个类被称为单例类,它提供全局访问方法。单例模式的要点有三个:

  • 某个类只能有一个实例
  • 它必须自行创建这个实例
  • 它必须自行向整个系统提供这个实例

二、懒汉式单例

代码实现如下:

public class LazyWaterCup {
    // 定义一个静态引用
    private static LazyWaterCup wc;

    // 构造方法私有
    private LazyWaterCup(){}

    // 提供一个全局访问点
    public static LazyWaterCup getInstance() {
        if (wc == null){
        	wc = new LazyWaterCup();
        }
        return wc;
    }
}

首先我们要声明一个类引用,其次构造方法必须是私有的,以保证外部对于此类无法直接通过new进行类的实例化,与此同时我们要提供一个对外的方法,在此方法中实现类的实例化,也需要进行一个判断,若类引用没有指向任何对象,就创建一个对象,让引用指向它。

测试结果如下:

public class Test {
    public static void main(String[] args) {
        LazyWaterCup lwc1 = LazyWaterCup.getInstance();
        LazyWaterCup lwc2 = LazyWaterCup.getInstance();
        LazyWaterCup lwc3 = LazyWaterCup.getInstance();
        System.out.println("lwc1= " + lwc1);
        System.out.println("lwc2= " + lwc2);
        System.out.println("lwc3= " + lwc3);
    }
}

在这里插入图片描述
如图三次调用都指向同一个对象,因为从第一个getInstance()被调用时,由于类引用指向->null所以会创建对象,后续再调用getInstance()方法就不会再创建对象而是将上一个对象地址返回。因此三次打印结果都是指向同一个对象。

三、饿汉式单例

代码如下:

public class HungryWaterCup {
    // 定义一个静态引用
    private final static HungryWaterCup wc = new HungryWaterCup();
    
    // 构造方法私有
    private HungryWaterCup(){}

    // 提供一个全局访问点
    public static HungryWaterCup getInstance() {
        return wc;
    }
}

饿汉式单例与懒汉式单例的区别在于它对于对象的创建比较急迫,在声明的时候就创建一个对象,使声明的引用指向它,它是在类的装载过程中就完成的。

测试结果如下:

public class Test {
    public static void main(String[] args) {
        HungryWaterCup hwc1 = HungryWaterCup.getInstance();
        HungryWaterCup hwc2 = HungryWaterCup.getInstance();
        HungryWaterCup hwc3 = HungryWaterCup.getInstance();
        System.out.println("hwc1= " + hwc1);
        System.out.println("hwc2= " + hwc2);
        System.out.println("hwc3= " + hwc3);
    }
}

在这里插入图片描述

四、懒汉式单例存在的线程安全问题

懒汉式单例是在getInstance()被调用的时候创建的,若此时有大量线程访问此方法,就会创建多个对象,我们可以测试一下:
在这里插入图片描述
在创建对象的时候先让线程睡眠1ms,方便模拟多线程环境。

public class Test {
    public static void main(String[] args) {
        for (int i = 0; i < 200; i++) {
            Thread t1 = new Thread(() -> {
                try {
                    LazyWaterCup lwc = LazyWaterCup.getInstance();
                    System.out.println("lwc->" + lwc);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }, "t1");
            t1.start();
        }
    }
}

在测试类代码中,创建200个线程。运行结果如下图:
在这里插入图片描述
创建的对象很多不一样。解决线程安全问题,一般可以在可能出现并发安全的代码块加上对象锁,就是synchronized锁,我们上锁之后,再试试:
在这里插入图片描述
测试结果:
在这里插入图片描述
就可以保证创建的对象是同一个。


总结

今天对单例模式的分析就到这里了,后续会继续总结其他设计模式的原理与实现。

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

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

相关文章

【前端知识】React 基础巩固(二十八)——StrictMode

React 基础巩固(二十八)——StrictMode StrictMode StrictMode 是一个用来突出显示应用程序中潜在问题的工具 与 Fragment 一样&#xff0c;StrictMode 不会渲染任何可见的 UI为后代出发额外的检测和警告严格模式检查仅在开发模式下运行&#xff0c;不影响生产构建 严格模式检…

Google DeepMind掌舵人Demis Hassabis专访:合并后「超级单元」内幕,以及如何开展下一代模型研究...

导读 自2023年以来&#xff0c;Google旗下两大顶级人工智能研究团队 DeepMind 与 Google Brain 被不断推上风口浪尖&#xff0c;如何应对OpenAI与微软强强联合&#xff1f;如何组织不被看好的 DeepMind 与 Google Brain 团队合并&#xff1f;Google和OpenAI都没有护城河吗&…

单片机第一季:零基础8——蜂鸣器

蜂鸣器是一种一体化结构的电子讯响器&#xff0c;采用直流电压供电&#xff0c;广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。 蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。 想要压电式蜂鸣器发声&…

使用Gataway设置全局过滤器

说明&#xff1a;Gateway网关是所有微服务统一的入口&#xff0c;通过网关技术&#xff0c;可以实现请求转发、权限控制和限流。全局过滤器是Gateway请求转发、权限控制的一个体现。比如对所有请求进行过滤&#xff0c;判断请求是否携带有效的token&#xff0c;对请求放行或者拦…

Java 装箱拆箱原理 包装类型缓存池

JAVA中的基本数据类型 byteshortintlongfloatdoublebooleanchar 为了让上述基本数据类型可以转为对象&#xff0c;Java在1.5推出了一系列包装类&#xff0c;基本类和包装类互相转换的过程&#xff0c;称为装箱和拆箱 缓存池 缓存池也叫常量池。它是事先存储一些常量数据用以…

reverse

b,a,0x7d65都能轻易的转成字符串&#xff0c;就是这个负数需要看汇编&#xff0c;在汇编层面是加了两个数实现的减法效果。 a[galf,saE{,er_y,3r0v,}e] for each in a:print(each[::-1],end) # flag{Easy_rev0r3e}

华为OD机试真题 Java 实现【路灯照明问题】【2022Q4 100分】,感谢fly晨发现这个问题,并提供更优质的算法

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路特别鸣谢&#xff1a;感谢fly晨发现这个问题&#xff0c;并提供更优质的算法。解题思路如下&#xff1a; 五、Java算法源码六、效果展示1、输入2、输出3、思路 专栏导读 本专栏收录于《华为OD机试&#xff08;J…

【USRP X310】如何查找USRP X310的 LabVIEW 案例 Demo

环境 Windows 10LabVIEWUSRP 支持的硬件 USRP-2900USRP-2901USRP-2920USRP-2921USRP-2922USRP-2930USRP-2932USRP-2940 40 MHzUSRP-2940 120 MHzUSRP-2942 40 MHzUSRP-2942 120 MHzUSRP-2943 40 MHzUSRP-2943 120 MHzUSRP-2944USRP-2945USRP-2950 40 MHzUSRP-2950 120 MHzUS…

轻奢分销商城pc/h5小程序开源版开发

轻奢分销商城pc/h5小程序开源版开发 商城系统&#xff1b;包含小程序商城、H5商城、公众号商城、PC商城、App&#xff0c;支持秒杀、优惠券、积分、分销、会员等级。 功能列表&#xff1a; 用户注册和登录&#xff1a;用户可以通过手机号码或第三方登录方式注册和登录账号。…

RPM包详解以及如何制作RPM包

RPM包简介 RPM 全名 RedHat Package Managerment&#xff0c;一开始只是Red Hat Linux的软件包格式&#xff0c;它最初的名字为Red Hat软件包管理程序。从那以后&#xff0c;RPM逐渐称为许多其他Linux发行版所接受的一种软件包格式。Linux标准化规范将RPM作为其官方软件包格式…

gdb调试产生code文件以及遇到的“file format not recognized”问题解决

一、调试 core 文件的配置 1.1 开启core文件 —— ulimit 有时候&#xff0c;服务器程序运行一段时间后会突然崩溃&#xff0c;这并不是我们希望看到的&#xff0c;需要 解决这个问题。只要程序在崩溃的时候有 core 文件产生&#xff0c;就可以使用这个 core 文件 来定位崩溃…

数据结构(王道)——线性表的存储结构之双链表

双链表和单链表的对比 一、从无到有创建一个双链表及其基础操作 带头结点 的双链表 初始化 双链表的后插操作&#xff1a; 从后插可以拓展到按位序插入&#xff0c;和前插操作。 因为双链表的特性&#xff0c;如果按位序插入或者前插操作&#xff0c;只需要找到插入的位置的前…

传统企业的数据管理:如何高效管理分散的数据?

在数字时代&#xff0c;数据管理已经成为一个重要的议题。大多数企业已经意识到数据是他们业务运营的重要组成部分。然而&#xff0c;许多传统企业还在使用过时的数据管理模式&#xff0c;这些模式并不具备高效管理分散数据的能力。随着企业的膨胀和数据规模的逐渐增加&#xf…

AI工程师:未来时代的主流工程师

自从以ChatGPT为主的人工智能&#xff08;AI&#xff09;大模型层出不穷&#xff0c;越来越多人开始意识到AI的潜力&#xff0c;甚至预测“所有行业都将通过AI来进行重塑”&#xff0c;正是基于该原因&#xff0c;各国各企业如火如荼建设AI事业&#xff0c;作为把AI造出来的AI工…

配合LaTex使用的“工具”

先介绍两个工具&#xff0c;比如公式的书写等&#xff0c;会大大提高书写论文的速度。 第一个&#xff1a;Mathpix Snip(生成公式)。官网&#xff1a;https://mathpix.com 【先去官网注册一个账号&#xff08;注册时遇到的问题见文章Mathpix上半部分&#xff09;然后去安装该软…

Python 列表 pop()函数使用详解

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 pop函数使用详解 1、按照索引删除元素1.1、正数索引1.2、负数索引1.3、不指定索引…

docker k8s

Docker docker到底与一般的虚拟机有什么不同呢&#xff1f; 我们知道一般的linux系统即GNU/Linux系统包括两个部分&#xff0c;linux系统内核GNU提供的大量自由软件&#xff0c;而centos就是众多GNU/Linux系统中的一个。 虚拟机会在宿主机上虚拟出一个完整的操作系统与宿主机完…

vue+openlayers 点击地图查询geoserver发布的WMS/WMTS图层的信息[矢量(点、线、面)+栅格]

一、基本介绍 网络地图服务 (WMS) 、网络地图切片服务 (WMTS) &#xff0c;根据用户的请求返回相应的地图&#xff08;包括PNG&#xff0c;GIF&#xff0c;JPEG等栅格形式或者是SVG和WEB CGM等矢量形式&#xff09;。 下面是常见的geoserver发布的图层格式&#xff0c;有矢量…

ODX(ISO22901)进阶——Intorduction to ODX

文章目录 前言一、Vehicle Diagnostic是什么?二、Diagnostic Data in ODX(诊断数据在ODX数据库)三、ODX企标概述(ODX Authoring Guidelines)总结前言 今天是2023年7月15日,距离2024年只剩下半年时间。伴随着各地疫情政策逐渐发开,三年的疫情终于迎来了不一样的变化。期…

AI绘画Stable Diffusion实战操作: 62个咒语调教-时尚杂志封面

今天来给大家分享&#xff0c;如何用sd简单的咒语输出好看的图片的教程&#xff0c;今天做的是时尚杂志专题&#xff0c;话不多说直入主题。 还不会StableDiffusion的基本操作&#xff0c;推荐看看这篇保姆级教程&#xff1a; AI绘画&#xff1a;Stable Diffusion 终极炼丹宝…