打通设计模式任督二脉 -- 单例模式
文章目录
- 1、设计模式介绍
- 2、单例模式
- 2.1、什么是单例模式?
- 2.2、单例模式实现方式
- 2.3、单例模式存在的问题
- 2.4、JDK源码中使用到的单例模式
前言:想必想了解设计模式的各位都是走开发路线的吧,那么既然是走开发路线的,那么设计模式可是一定要好好学哦。因为它是一种思想,将会贯彻到你的开发过程,同时如果你使用的得当的话,那么你的项目将会十分的流畅且亮点丰富。当然这也是开始学之前的一些废话。总之,脚踏实地好好学。
1、设计模式介绍
我们得先从设计模式的定义出发。哈哈,不知道你们学习东西的流程是什么。反正我学习的一个流程是先要知道这个东西是什么,然后再知道为什么要学习这个东西,然后就是怎样使用这个东西了。这个是学习东西的一个方法和套路,我们需要总结出自己的一个学习新事物的套路来,这样才能事半功倍。
什么是设计模式?
那么什么是设计模式呢?
- 官方的定义:软件设计模式,又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。
- 说到底,它就是面向对象设计原则的实际运用思想和经验总结,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。
通过上述的定义的描述,大家肯定都对设计模式有了一定的初步的印象了,但是要进行深刻理解的话,这样还是不够的,需要之后对各个设计模式的学习理解和消化。
为什么要使用设计模式呢?
- 可以提高程序员的思维能力、编程能力和设计能力。
- 使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。
- 使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。
2、单例模式
我们上面简单的介绍了一下设计模式是什么,为什么要学习设计模式,之后我们将从各个设计模式的使用来进行讲解。记住,设计模式是一种思想,我们一定要尽可能地理解它。当然,如果暂时理解不了的话,也不要灰心,慢慢来消化即可。加油吧,骚年!!!
2.1、什么是单例模式?
单例模式(英文名:Singleton Pattern
)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建(所以说如果该类是单例模式的话,那么你使用到的它的每一个对象都是相同的。)
。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
- 单例模式的主要有以下角色:
- 单例类:
只能创建一个实例的类
- 访问类:使用单例类
2.2、单例模式实现方式
单例设计模式分类两种(主要区别在于是否在类加载的时候进行相关单实例对象的创建):
饿汉式
:类加载就会导致该单实例对象被创建
懒汉式
:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建
饿汉式 - 方式1
/*** @author :小肖* 饿汉式方式1:静态成员变量* @date :Created in 2022/5/5 14:58*/
public class Singleton {// 1. 私有构造private Singleton() {}// 2. 静态成员变量private static Singleton instance = new Singleton();// 3. 公有的获取方法public static Singleton getInstance() {return instance;}
}
测试方法
/*** @author :小肖* @date :Created in 2022/5/5 15:00*/
public class Test {public static void main(String[] args) {// 获取第一个实例Singleton instance = Singleton.getInstance();// 获取第二个实例Singleton instance1 = Singleton.getInstance();// 比较两个实例是否相等System.out.println(instance == instance1);}
}
输出结果
true
饿汉式 - 方式2
/*** @author :小肖* 饿汉式方式2:静态代码块* @date :Created in 2022/5/5 15:05*/
public class Singleton {// 1. 私有构造private Singleton() {}// 2. 私有静态变量private static Singleton instance;// 3. 静态代码块进行创建对象static {instance = new Singleton();}// 4. 公有的获取方式public static Singleton getInstance() {return instance;}
}
总的说明:我们观察上述的代码可以发现,我们是将对应的类的构造方法私有,进而防止外部进行创建该类对象,同时在类内部直接创建好对象,从而使得对象是单例的,但可能创建的方式不同。但不管是使用静态代码块的方式创建对象,还是直接创建对象,它们都是在类加载的时候就进行了相关对象的创建,如果我们之后没有对其进行使用,或者说之后的代码中并未使用到该对象,那么这样加载的对象就是浪费了相关内存的。这也是饿汉式的缺点所在,那么也就引申出了 懒汉式实现方式
。
懒汉式 - 线程不安全
/*** @author :小肖* 懒汉式实现* @date :Created in 2022/5/5 15:23*/
public class Singleton {// 1. 私有构造方法private Singleton() {}// 2. 静态成员变量private static Singleton instance; // null// 3. 公有获取方法public static Singleton getInstance() {if (instance == null) {return new Singleton();}return instance;}
}
为什么线程不安全呢?
当线程1读取到当前 instance
为 null
的时候,那么此时如果就将 cpu
让出给线程2使用的话,那么此时线程2 读取到的当前 instance
也为 null
,那么就会导致两个线程创建了多个实例对象,所以在多线程环境下是不安全的。
懒汉式 - 线程安全
/*** @author :小肖* 懒汉式实现* @date :Created in 2022/5/5 15:23*/
public class Singleton {// 1. 私有构造方法private Singleton() {}// 2. 静态成员变量private static Singleton instance; // null// 3. 公有获取方法public static synchronized Singleton getInstance() {if (instance == null) {return new Singleton();}return instance;}
}
虽然这种方式能够解决多线程线程安全问题,但是你要知道 synchronized
是重量级锁,虽然 JVM
底层对它进行了相关的优化,但是还是会带来很大的性能消耗。因为这个方法大多数情况下是读操作,所以只有当需要创建对应的实例对象的时候才需要进行对应的加锁的必要,那么我们可以使用 双重检查锁 + volatile
实现一种更好的单例模式。
懒汉式 - 线程安全(双重检查锁 + volatile)
/*** @author :小肖* 懒汉式 双重检查锁 + volatile* @date :Created in 2022/5/5 15:48*/
public class Singleton {// 1. 私有构造private Singleton() {}// 2. 静态成员变量private static volatile Singleton instance;// 3. 公有获取方式public static Singleton getInstance(){if(instance == null){synchronized (Singleton.class){if(instance == null){return instance;}}}return instance;}
}
这里需要注意,我们为什么要在对应的变量上加 volatile
关键字呢?
因为在多线程的情况下,它还是会造成我们对应的单例对象是空指针的情况,该情况主要是由于虚拟机优化和指令重排造成的。所以说我们可以通过加上 volatile
使得消除这种指令重排。
当然这里还有两种实现单例模式的方式:静态内部类的实现方式、枚举的实现方式
。这里我就不一一介绍了。
2.3、单例模式存在的问题
其实单例模式维护的核心就是保证对应的实例对象是唯一的,那么就肯定会有人想方设法的去破环这种唯一性。这就是单例模式所存在的问题了。
破坏方式
- 通过序列化和反序列化的方式可以对单例模式进行破坏。
- 通过反射机制可以对单例模式进行破坏。
解决方式
- 在
Singleton
类中添加readResolve()
方法,在反序列化时被反射调用,如果定义了这个方法,就返回这个方法的值,如果没有定义,则返回新new
出来的对象。 - 当通过反射方式调用构造方法进行创建时,如果对应的对象为
null
的话,直接抛异常。
2.4、JDK源码中使用到的单例模式
Runtime
类就是使用的单例设计模式。
public class Runtime {private static Runtime currentRuntime = new Runtime();/*** Returns the runtime object associated with the current Java application.* Most of the methods of class <code>Runtime</code> are instance* methods and must be invoked with respect to the current runtime object.** @return the <code>Runtime</code> object associated with the current* Java application.*/public static Runtime getRuntime() {return currentRuntime;}/** Don't let anyone else instantiate this class */private Runtime() {}...}
从上面源代码中可以看出 Runtime
类使用的是饿汉式(静态属性)方式来实现单例模式的。
编写不易,如果你感觉对你有帮助的话,请你三连支持,后面的文章会一点点更新。
打通设计模式任督二脉 -- 单例模式相关推荐
- 安卓影像飞升时刻:vivo X90 Pro+打通HDR任督二脉
在手机产业中,大多数人会有一种刻板印象:一项新技术/功能,苹果发布会上展示意味着已经成熟,具有很高的产品完成度,好用且有效:而安卓厂商在发布会上展示出的一些炫酷技术,往往还需要时间观望,才能确定是不是 ...
- shell,打通 Linux 任督二脉,任何武功都随你所用
文章目录 护花使者 shell 的工作原理 shell 的必要性 shell 的功能 shell 的优越性 系统的合法 shell bash shell 的功能 总结 护花使者 管理整个计算机硬件的其 ...
- 打通物联网任督二脉,海天味业畅谈AI+大数据
2018年11月24日,由中国计算机学会CCF主办,中国计算机学会青年工作委员会和CCF YOCSEF深圳分论坛共同承办的主题为"大数据及人工智能将如何打通物联网的任督二脉"活动在 ...
- 下一波模式移转-订制化制造 打通物联网任督二脉
订制化制造可望打通发展物联网产业的任督二脉.由于各种终端装置都可连网.互动,势将衍生许多新兴应用与服务的发展空间.物联网产业已是大厂竞相投入的兵家必争地,也为新创企业打开机会之窗,可思考发展建构订制化 ...
- BPM流程管理协助打通企业管理“任督二脉”
编者按:在数字化时代,企业对于风险管控.流程效率有了更高的要求,随着业务的增长,管理工作流程变得更为繁琐,为避免形成数据孤岛,天翎自研的BPM业务流程管理为提高企业的整体运行效率和效益,增强企业的核心 ...
- 60小时打通Python任督二脉
重磅:教育部考试中心已经公布,在计算机二级考试加入"Python语言程序设计"科目,将于2018年9月全国计算机等级考试中首次亮相.这将促进Python在大学生中的普及. 教育部也 ...
- 阿里架构专家教你打通Git任督二脉,20分钟搞定Git工作原理
如何配置本地的git环境并拉取代码? 1.下载 git ,选择自己系统对应的版本下载即可. 2.在你的电脑上生成 ssh 秘钥,打开终端,执行 ssh-keygen -t rsa -C "你 ...
- 一文打通 Git 任督二脉
Git 一.概述 二.Git的安装 三.常用命令 1.配置命令 2.基本命令 3.git reset 4.分支命令 四.git文件状态 五.忽略文件 六.Git团队协作示意图 七.GitHub基本使用 ...
- 打通 Java 任督二脉 —— 并发数据结构的基石
老大难的 Java ClassLoader,到了该彻底理解它的时候了 每一个 Java 的高级程序员在体验过多线程程序开发之后,都需要问自己一个问题,Java 内置的锁是如何实现的?最常用的最简单的锁 ...
最新文章
- BCH虫洞项目存在不足,但更值得期待!
- Kali Linux搜索软件包
- php json注释,【部分解决】Json中添加注释
- Django REST framework+Vue 打造生鲜电商项目(笔记八)
- php实现上传图片保存到数据库的方法
- CodeForces - 1288E Messenger Simulator(树状数组)
- java buffalo_随你怎么玩!Buffalo 网络硬盘新潮流
- ServletContentLIstener接口演示ServletContext的启动和初始化
- Linux 命令(78)—— rmdir 命令
- 全网首发:LINUX右键新建时的模板问题
- 拼图·面部表情捕捉 | design-ai-lab
- jenkins 版本升级
- VS2005/SQL2005等原版镜像高速下载
- 耳机不分主从是什么意思_音质出色,降噪服众,千元机档位王者南卡A1主动降噪耳机深度评测...
- yolov3 NMS非极大值抑制
- python爬虫 知乎_python爬虫——知乎(关于python的精华回答)
- 缺陷特征描述及特征选择
- Meta被裁员工流向TikTok/ 比亚迪半导体IPO终止/ NASA登月火箭今日发射…今日更多新鲜事在此...
- 阿里内贸团队敏捷实践
- SPSS常用的10种统计分析
热门文章
- RIGOL普源DS2202A示波器 100M数字储存示波器
- ArcGIS Engine空间分析之拓扑分析的实现
- 扫地机器人的轮子困住_扫地机器人防困住卡死的解决方案
- 电脑PDF怎么转换成Word?这3招总有一个能用上
- HDU - 4489 The King’s Ups and Downs(dp)
- Google login 踩坑之后的注意事项
- python两个线程交替执行_python 实现两个线程交替执行
- 丁晓钟怎么样_考研英语辅导书那么多到底该怎么选?听听过来人的意见
- android 字体管家,手机字体管家 安卓版
- Oracle数据库的体系结构和用户管理