Java设计模式-单例模式(2)

图片

    大家好,我是馆长!从今天开始馆长开始对java设计模式的创建型模式中的单例、原型、工厂方法、抽象工厂、建造者单例模式进行讲解和说明。

单例模式(Singleton)

定义

    某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。

目的

    节省内存资源、保证数据内容的一致性,对某些类要求只能创建一个实例,这就是所谓的单例模式。

特点

1.单例类只有一个实例对象;

2.该单例对象必须由单例类自行创建

3.单例类对外提供一个访问该单例的全局访问点

优点:

  • 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。

  • 避免对资源的多重占用(比如写文件操作)。

缺点:

    没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

结构

单例模式的主要角色如下。

·单例类:包含一个实例且能自行创建这个实例的类。

·访问类:使用单例的类。

图片

注意点

1.单例模式是自关联关系设计。

2.字段 instance 为private,static, volatile修饰。

3.getInstance(全局访问点)为public ,static 修饰,其中涉及了 synchronized关键字的使用 。

4. 构造函数为private(私有的)。

volatile:

        volatile关键字是为了保证线程安全的,当某个线程对共享变量只是读操作而没有写操作时,使用volatile就可以保证线程安全。volatile的作用是保证可见性和有序性,因为读操作本来就具有原子性,因此仅使用volatile就可以保证线程安全。

synchronized:

        多个线程使用同一个对象进行加锁(基于对象头加锁),可以实现线程间的同步互斥。简单地说,它的原理就是基于对象头加锁,满足原子性、可见性、有序性。

懒汉式(线程安全)

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。

public class LazySingleton {//保证 instance 在所有线程中同步private static volatile LazySingleton instance = null;private LazySingleton() {}    //private 避免类在外部被实例化//synchronized 修饰方法级别public static synchronized LazySingleton getInstance() {//getInstance 方法前加同步if (instance == null) {instance = new LazySingleton();}return instance;}
}

懒汉式(线程不安全)

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。

public class LazySingleton {private static LazySingleton instance;private LazySingleton (){}public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}
饿汉式(线程安全)

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述:这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存

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

【推荐】双检锁/双重校验锁(DCL,即 double-checked locking)

JDK 版本:JDK1.5 起

是否 Lazy 初始化:

是否多线程安全:

实现难度:较复杂

描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。getInstance() 的性能对应用程序很关键。

public class Singleton {private volatile static Singleton singleton;private Singleton (){}public static Singleton getSingleton() {if (singleton == null) {synchronized (Singleton.class) {if (singleton == null) {singleton = new Singleton();}}}return singleton;}
}

登记式/静态内部类

是否 Lazy 初始化:

是否多线程安全:

实现难度:一般

描述:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。调用getInstance()方法时才创建,达到了类似懒汉式的效果,同时又是线程安全的。

public class Singleton {private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}private Singleton (){}public static final Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

枚举

JDK 版本:JDK1.5 起

是否 Lazy 初始化:

是否多线程安全:

实现难度:

优点:线程安全,不用担心反射破坏单例模式,性能高,没有任何锁。

缺点:枚举类占用内存多。

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

public enum Singleton {INSTANCE;public void otherMethod() {//处理其他功能业务}
}

        23 种设计模式不是孤立存在的,很多模式之间存在一定的关联关系,在大的系统开发中常常同时使用多种设计模式,或者模式与模式之间的组合进行生成更加强大的程序功能。

    好了,关于单例模式的说明,馆长就先讲到这里,最近馆长了解到单例模式实现不仅仅是上述的几种,随着软件行业的发展,各种变种也开始流行。由于时间和精力问题,馆长就先整理这些。谢谢各位看官!!


馆长准备了很多学习资料,其中包含java方面,jvm调优,spring / spring boot /spring cloud ,微服务,分布式,前端,js书籍资料,视频资料,以及各类常用软件工具,破解工具 等资源。请关注“IT技术馆”公众号,进行关注,馆长会每天更新资源和更新技术文章等。请大家多多关注。

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

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

相关文章

AI如何助力制造业变革?

当前,制造业企业正在转型发展,发力智能制造,以实现降低成本、提高效率和提高客户满意度的目标。这其中人工智能(AI)被认为是最重要的一项技术。AI技术可以优化制造流程,大大提高生产力,帮助企业…

houdini rnn

1.3.RNN模型_哔哩哔哩_bilibili 此公式来自于吴恩达P1.3视频 按公式推测rnn内部结构,如有错误,敬请指正

【话题】边缘计算的挑战和机遇

边缘计算是一种新的计算范式,其核心是在网络边缘处理数据,而不是传统的中心式云计算模式。这种计算方式的兴起得益于物联网(IoT)的普及和丰富的云服务的成功。 机遇: 响应时间优化:由于数据处理更接近数据…

解决系统开发中的跨域问题:CORS、JSONP、Nginx

文章目录 一、概述1.问题场景2.浏览器的同源策略3.解决思路 二、一点准备工作1.创建前端工程12.创建后端工程3.创建前端工程24.跨域问题 三、方法1:使用CORS四、方法2:JSONP五、方法3:Nginx1.安装和启动(windows)2.使用…

初识VUE

文章目录 Vue是什么1.创建一个Vue实例2.插值表达式{{ }}3.Vue的响应式特性4.开发者工具的安装 Vue是什么 概念:Vue是一个用于构建用户界面的渐进式框架 ①构建用户界面:基于数据渲染出用户看到的界面 ②渐进式:循序渐进 ③ 框架&#xff1…

Flask用于生产环境

Flask是一个用Python编写的轻量级Web应用框架,可以用于开发和部署Web服务。要安装Flask,您需要以下步骤: - 安装Python和pip,如果您还没有的话。 - 创建一个虚拟环境,以便隔离您的Flask应用程序和其他Python项目。 - …

MySQL经典面试题

目录 1、查询课程名称为“数据库”,且分数低于60分的学生姓名和分数 2、对所有性别为“女”的学生,同时课程名为“高等数学”的分数统一加5 3、删除姓名为“张翰”(学号1)课程名为“数据库”的课程成绩 4、统计2021年11月每天…

6.4.4释放音频

6.4.4释放音频 许多Flash动画里的音乐或歌曲非常好听,能不能在没有源文件的情况下把里面的声音文件取出来呢?利用Swf2VideoConverter2可以轻松做到这一点。 1.单击“添加”按钮,在弹出的下拉菜单中选择“添加文件”,…

金蝶云星空表单插件获取单据体数据

文章目录 金蝶云星空表单插件获取单据体数据 金蝶云星空表单插件获取单据体数据 使用标识报错 var thisEntry this.View.Model.DataObject["FEntity"] as DynamicObjectCollection;应该使用实体属性 var thisEntry this.View.Model.DataObject["BillEntry&q…

搜索经典题——填充 9*9矩阵

题目:给定一个九行九列矩阵,填充矩阵元素,要求: 1、每一行每一列,每个小九宫格(图片画粗的地方就是)不能包含相同元素 2、每一行,每一列,每个小九宫格均会完整出现1-9的数…

面试题目,你对前端工程化的了解

前端工程化是通过工具和流程来提高软件开发效率、降低维护成本以及改善项目可维护性的方法。在前端领域,前端工程化通常包括以下方面内容 版本控制 使用 git 来管理代码的版本,追踪变更,协作开发等项目脚手架 使用项目的脚手架进行项目的初始…

【Python爬虫】项目案例讲解,一步步教你爬取淘宝商品数据!

前言 随着互联网时代的到来,人们更加倾向于互联网购物,某宝又是电商行业的巨头,在某宝平台中有很多商家数据,今天带大家使用pythonselenium工具获取这些公开的商家数据 环境介绍: python 3.6pycharmseleniumcsvtime…

SpringBoot自动装配原理及分析

一、什么是自动装配 在使用SpringBoot的时候,会自动将Bean装配到IOC容器中。例如我们在使用Redis数据库的时候,会引入依赖spring-boot-starter-data-redis。在引入这个依赖后,服务初始化的时候,会将操作Redis需要的组件注入到Ioc…

vue3 项目中 arguments 对象获取失败问题

问题 在 vue3 项目中 获取到的 arguments 对象与传入实参不符,打印出函数中的 arguments 对象显示如下: 原因 作者仔细回看代码才发现,自己一直用的是 vue3 的组合式写法,函数都是箭头函数,而箭头函数不存在 argumen…

故障诊断传感器的位置会影响振动信号分类的精度吗?

问题描述:故障诊断传感器的位置会影响振动信号分类的精度吗? 问题解答: 是的,故障诊断中传感器的位置确实可能会影响振动信号分类的精度。 首先,传感器的位置决定了能够采集到的振动信号的特性。如果传感器靠近故障…

cetos7搭建部署k8s 版本1.28

主机分配 内存最少是4G cpu个数最少两个 IP内存CPU主机名192.168.231.12044K1 192.168.231.12144K2192.168.231.12244K3 关闭防火墙 systemctl stop firewalled 关闭swap vim /etc/fstab 设置主机名称 hostnameset 安装docker 三个主机 初始化集群 在mas…

1432 - 走出迷宫的最少步数-广度优先搜索BFS

代码 #include<bits/stdc.h> using namespace std; char a[51][51]; int r,c; int fx[4]{0,0,1,-1}; int fy[4]{1,-1,0,0}; int tx,ty; struct Node{int x,y,step; }; int bfs(int x,int y){a[x][y]#;queue<Node> q;q.push({x,y,1});while(!q.empty()){Node Curre…

第五篇:其他窗口部件 QAbstractButton

QAbstractButton QAbstractButton 类是按钮部件的抽象基类&#xff0c;提供了按钮的通用功能。它的子类包括标准按钮 QPushButton、工具按钮 QToolButton、复选框 QCheckBox和单选按钮 QRadioButton 等。 QPushButton QPushButton 提供了创建交互按钮的基本功能。它可以包含…

openssl3.2 - 官方demo学习 - smime - smenc.c

文章目录 openssl3.2 - 官方demo学习 - smime - smenc.c概述笔记END openssl3.2 - 官方demo学习 - smime - smenc.c 概述 读取X509证书, 用PKCS7加密明文(证书 明文 3DES_CBC), 保存为MIME格式的密文 openssl API的命名含义 BIO_new_file “new” a “file”, return a “…

开发安全之:Server-Side Request Forgery

Overview 函数 fsockopen() 将使用资源 URI 的用户控制数据启动与第三方系统的网络连接。攻击者可以利用此漏洞代表应用程序服务器发送一个请求&#xff0c;因为此请求将自应用程序服务器内部 IP 地址发出。 Details 当攻击者可以影响应用程序服务器建立的网络连接时&#xf…