单例模式:控制实例创建数目-阿里云开发者社区

开发者社区> 5abyqn7wigzqm> 正文

单例模式:控制实例创建数目

简介: 单例模式的本质是在于控制实例创建数目
+关注继续查看

场景分析

多个客户端通过new 多个配置对象的实例来获取配置内容,而配置对象的获取的内容都是一样的,只需要一个实例即可。多个配置对象严重浪费系统内部资源。

image.png
定义及本质

定义:保证一个类只有一个实例,并提供一个访问它的全局访部点。
本质:控制实例创建数目。
功能:保证类在运行期间只会被创建一个类的实例。
范围:一个虚拟机的范围,如果一台机器有多个虚拟机,每个虚拟机都会有一个类的实例,这个类就是多例;
命名:getInstance()
结构示意图:

image.png

解决方案
1 懒汉式
一个私有化构造器、一个静态方法、一个静态属性
延迟加载思想:一开始不需要加载资源或数据,等使用的时候再加载,节约资源。
缓存思想:当某资源或数据频繁被使用,将其缓存到内存中,节省时间,典型的以空间换时间的方案。
2 饿汉式:利用static特性
static 变量在类装载的时候进行初始化;
多个实例的static 变量会共享同一块内存区域;
3 静态内部类实现单例,延迟加载(类级内部类)
Lazy initialization holder class模式,这个模式综合使用了Java的类级内部类和多线程缺省同步锁的知识,很巧妙的同时实现了延迟加载和线程安全。
类级内部类可以让类装载时不去初始化对象,只要不使用到这个类级内部类,就不会创建对象实例。

(1)Java的类级内部类
什么是类级内部类?

类级内部类指的是:有static修饰的成员式内部类。如果没有static修饰的成员式内部类被称为对象级内部类。

类级内部类相当于其外部类的static成分,它的对象与外部类对象间不存在依赖关系,因此可直接创建。而对象级内部类的实例,是绑定在外部对象实例中的。
类级内部类中,可以定义静态的方法,在静态方法中只能够引用外部类中的静态成员方法或者成员变量。
类级内部类相当于其外部类的成员,只有在第一次被使用的时候才会被装载
(2)多线程缺省同步锁
为了解决并发问题,主要是通过使用synchronized来加互斥锁进行同步控制。但是在某些情况中,JVM已经隐含地执行了同步,这些情况下就不用自己再来进行同步控制了。
由静态初始化器(在静态字段上或 static{} 块中的初始化器)初始化数据时;
访问 final 字段时;
在创建线程之前创建对象时;
线程可以看见它将要处理的对象时;

枚举类实现单例
(1)枚举类型的基本思想
通过公有的静态final域为每个枚举常量导出实例的类。枚举是单例的泛型化,本质上是单元素的枚举。
(2)枚举实现单例的好处
自由序列化(枚举本身已实现Serializable接口);
线程安全(通过静态final域实现,JVM初始化时线程安全);
简洁易用;

UML类图
image.png

调用时序图
image.png

优缺点
(1)时间和空间
懒汉式是典型的时间换空间:每次获取实例时先要判断是否需创建实例。
饿汉式是典型的空间换时间:类装载时就会创建类实例;
(2)线程安全
懒汉式是非线程安全的,饿汉式是线程安全的(类装载时没有并发);
懒汉式安全实现机制:
第一种:加上synchronized,每次进入getInstance方法都需要同步,降低了访问速度;
第二种:双重检查加锁

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
我为什么要放弃 RESTful,选择拥抱 GraphQL
REST作为一种现代网络应用非常流行的软件架构风格,自从Roy Fielding博士在2000年他的博士论文中提出来到现在已经有了20年的历史。它的简单易用性,可扩展性,伸缩性受到广大Web开发者的喜爱。
9 0
为什么 MySQL 不推荐默认值为 null ?
通常能听到的答案是使用了NULL值的列将会使索引失效,但是如果实际测试过一下,你就知道IS NULL会使用索引,所以上述说法有漏洞。
12 0
这样统计代码执行耗时,才足够优雅!
代码耗时统计在日常开发中算是一个十分常见的需求,特别是在需要找出代码性能瓶颈时。 可能也是受限于 Java 的语言特性,总觉得代码写起来不够优雅,大量的耗时统计代码,干扰了业务逻辑。特别是开发功能的时候,有个感受就是刚刚开发完代码很清爽优雅,结果加了一大堆辅助代码后,整个代码就变得臃肿了,自己看着都挺难受。因此总想着能不能把这块写的更优雅一点,今天本文就尝试探讨下“代码耗时统计”这一块。
10 0
Slf4j 包老冲突,每次排查半天,是什么原因?怎么解决?
一、前言 在进行 Java 开发时,通常我们会选择 Slf4j 作为日志门面,但日志实现却不尽相同。如果系统运行中同时存在多个日志实现,就会出现类似下图的 Warning。
10 0
Google 开源的依赖注入库,比 Spring 更小更快!
Guice是Google开源的一个依赖注入类库,相比于Spring IoC来说更小更快。Elasticsearch大量使用了Guice,本文简单的介绍下Guice的基本概念和使用方式。
10 0
首长,Redis 性能优化十三条军规立好了,请过目~
Redis作为高性能的内存数据库,在大数据量的情况下也会遇到性能瓶颈,日常开发中只有时刻谨记优化铁则,才能使得Redis性能发挥到极致。 本文将会介绍十三条性能优化军规,开发过程中只要按照执行,性能必能质的飞跃。
19 0
听说 Spring AOP 有坑?那就来踩一踩
前言 前几日,有朋友分享了这样一个案例: 原来的项目一直都正常运行,突然
10 0
我为什么要放弃 RESTful,选择拥抱 GraphQL
REST作为一种现代网络应用非常流行的软件架构风格,自从Roy Fielding博士在2000年他的博士论文中提出来到现在已经有了20年的历史。它的简单易用性,可扩展性,伸缩性受到广大Web开发者的喜爱。
10 0
【保姆级教程】Spring Boot 单元测试
【保姆级教程】Spring Boot 单元测试 一、 单元测试的概念 概念: \1. 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。在Java中单元测试的最小单元是类。
8 0
34
文章
1479
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载