单例对象会被jvm的gc时回收吗_设计模式专题02-单例五种创建方式
单例五种创建方式(下一篇:工厂模式)
什么是单例
保证一个类只有一个实例,并且提供一个访问该全局访问点
单例应用场景
1. Windows的Task Manager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗? 不信你自己试试看哦~
2. windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。
3. 网站的计数器,一般也是采用单例模式实现,否则难以同步。
4. 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
5. Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。
6. 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。
7. 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。
8. 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。
9. HttpApplication 也是单位例的典型应用。熟悉ASP.Net(IIS)的整个请求生命周期的人应该知道HttpApplication也是单例模式,所有的HttpModule都共享一个HttpApplication实例.
单例优缺点
优点:
1.在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。这样就 防止其它对象对自己的实例化,确保所有的对象都访问一个实例
2.单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。
3.提供了对唯一实例的受控访问。
4.由于在系统内存中只存在一个对象,因此可以 节约系统资源,当 需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。
5.允许可变数目的实例。
6.避免对共享资源的多重占用。
缺点:
1.不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
2.由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
3.单例类的职责过重,在一定程度上违背了"单一职责原则"。
4.滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。
单例创建方式
1. 饿汉式:类初始化时,会立即加载该对象,线程天生安全,调用效率高。
2. 懒汉式: 类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象,具备懒加载功能。
3. 静态内部方式:结合了懒汉式和饿汉式各自的优点,真正需要对象的时候才会加载,加载类是线程安全的。
4. 枚举单例: 使用枚举实现单例模式 优点:实现简单、调用效率高,枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞, 缺点没有延迟加载。
5. 双重检测锁方式 (因为JVM本质重排序的原因,可能会初始化多次,不推荐使用)
饿汉式
//饿汉式
public class SingletonDemo01 {
// 类初始化时,会立即加载该对象,线程天生安全,调用效率高
private static SingletonDemo01 singletonDemo01 = new SingletonDemo01();
private SingletonDemo01() {
System.out.println("SingletonDemo01初始化");
}
public static SingletonDemo01 getInstance() {
System.out.println("getInstance");
return singletonDemo01;
}
public static void main(String[] args) {
SingletonDemo01 s1 = SingletonDemo01.getInstance();
SingletonDemo01 s2 = SingletonDemo01.getInstance();
System.out.println(s1 == s2);
}
}
懒汉式
//懒汉式public class SingletonDemo02 { //类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象。private static SingletonDemo02 singletonDemo02; private SingletonDemo02() { } public synchronized static SingletonDemo02 getInstance() {if (singletonDemo02 == null) {singletonDemo02 = new SingletonDemo02();}return singletonDemo02;} public static void main(String[] args) {SingletonDemo02 s1 = SingletonDemo02.getInstance();SingletonDemo02 s2 = SingletonDemo02.getInstance();System.out.println(s1 == s2);} }
静态内部类
// 静态内部类方式public class SingletonDemo03 {private SingletonDemo03() { System.out.println("初始化..");} public static class SingletonClassInstance {private static final SingletonDemo03 singletonDemo03 = new SingletonDemo03();} // 方法没有同步public static SingletonDemo03 getInstance() {System.out.println("getInstance");return SingletonClassInstance.singletonDemo03;} public static void main(String[] args) {SingletonDemo03 s1 = SingletonDemo03.getInstance();SingletonDemo03 s2 = SingletonDemo03.getInstance();System.out.println(s1 == s2);}}
优势:兼顾了懒汉模式的内存优化(使用时才初始化)以及饿汉模式的安全性(不会被反射入侵)。
劣势:需要两个类去做到这一点,虽然不会创建静态内部类的对象,但是其 Class 对象还是会被创建,而且是属于永久带的对象。
枚举方式
什么是枚举
枚举本身是单例的,一般用于项目中定义常量。
enum UserEnum {
HTTP_200(200, "请求成功"),HTTP_500(500,"请求失败");
private Integer code;
private String name;
UserEnum(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getName() {
return /使用枚举实现单例模式 优点:实现简单、枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞 缺点没有延迟加载
public class User {
public static User getInstance() {
return SingletonDemo04.INSTANCE.getInstance();
}
private static enum SingletonDemo04 {
INSTANCE;
// 枚举元素为单例
private User user;
private SingletonDemo04() {
System.out.println("SingletonDemo04");
user = new User();
}
public User getInstance() {
return user;
}
}
public static void main(String[] args) {
User u1 = User.getInstance();
User u2 = User.getInstance();
System.out.println(u1 == u2);
}
}
name;
}
public void setName(String name) {
this.name = name;
}
}
public class TestEnum {
public static void main(String[] args) {
System.out.println(UserEnum.HTTP_500.getCode());
}
}
双重检测锁
public class SingletonDemo04 {
private SingletonDemo04 singletonDemo04;
private SingletonDemo04() {
}
public SingletonDemo04 getInstance() {
if (singletonDemo04 == null) {
synchronized (this) {
if (singletonDemo04 == null) {
singletonDemo04 = new SingletonDemo04();
}
}
}
return singletonDemo04;
}
}
单例防止反射漏洞攻击
在构造函数中,只能允许初始化化一次即可。
private static boolean flag = false; private SingletonDemo04() { if (flag == false) {flag = !flag;} else {throw new RuntimeException("单例模式被侵犯!");}} public static void main(String[] args) { }
如何选择单例创建方式
如果不需要延迟加载单例,可以使用枚举或者饿汉式,相对来说枚举性好于饿汉式。
如果需要延迟加载,可以使用静态内部类或者懒汉式,相对来说静态内部类好于懒汉式。
单例对象会被jvm的gc时回收吗_设计模式专题02-单例五种创建方式相关推荐
- 单例对象会被jvm的gc时回收吗_【PHP设计模式】单例模式
前言 设计模式是我们开发过程中的重中之重,所以今天小编就来学习设计模式中的单例模式. 单例模式 <?phpclass Singleton { /*** 定义一个静态变量保存已经实例化的对象* * ...
- JVM内功心法-GC垃圾回收之GC垃圾回收过程
JVM内功心法-GC垃圾回收之GC垃圾回收算法 GC 全称garbagecollection,垃圾回收.JAVA 为了屏蔽操作系统和平台之间的差异.选择的是采用 java 虚拟机来运行 java 应用 ...
- JavaScript对象的几种创建方式?
**` JavaScript对象的几种创建方式? `**
- 设m,n均为自然数,m可表示为一些不超过n的自然数之和, f(m,n)为这种表示方式的数目。 例:f(5,3)=5,有五种表示方式: 3+2,3+1+1,2+2+1,2+1+1+1,1+1+1+1+1
(中科院软件所 1997 )m可表示为一些不超过n的自然数之和 设m,n均为自然数,m可表示为一些不超过n的自然数之和, f(m,n)为这种表示方式的数目. 例:f(5,3)=5,有五种表示方式: 3 ...
- 【JVM】GC垃圾回收(三)——零落成泥碾作尘,只有香如故
[引子] 当世界上最后一个记得我的生命也忘记了我的时候,我该如何自处呢?我想我会最后看一眼我深爱的故乡,然后将占用这个世界的最后一缕精华也散去,让灵魂永归沉寂.GC垃圾回收机制也是如此,每一个最终消亡 ...
- JVM与GC垃圾回收(各种垃圾收集器,Jvm相关工具)
1.JVM内存区域: 虚拟机栈,本地方法栈,程序计数器线程隔离,方法区,本地内存,直接内存,堆线程共享. ①.虚拟机栈:描述方法执行时的内存模型, 主要保存执行方法时的局部变量表.操作数栈.动态连接和 ...
- 详解JVM和GC垃圾回收
文章目录 JVM架构图分析 Java虚拟机运行时数据区 对象的创建方式有几种? 创建对象的过程 对象的访问定位 垃圾回收机制 如何判断一个对象是否可以回收 垃圾回收算法都有哪些? 对象分代 垃圾回收器 ...
- 创建函数查找上级_一文秒懂JavaScript中对象的7种创建方式
1.工厂模式 javascript 代码 工厂模式:能根据接受的参数来创建出一个person对象.也可以无数次的调用这个函数,每次都会返回一个包含3个属性和1个方法的对象. 工厂模式虽然解决了创建多个 ...
- axios post传递对象_axios的post传参时,将参数转为form表单格式
import axios from 'axios'; import alert from './alert.js'; import Qs from 'qs' //引入qs 时axios的自带模块 le ...
最新文章
- 完美解决opencv-python中文路径解析问题
- 寻找阿姆斯特朗数c语言程序,C程序检查阿姆斯特朗数
- Hive SQL开窗函数详解
- 8.python之面相对象part.6(反射__call__,__setattr__,__delattr__,__getattr__)
- jQuery.fn.extend()方法
- qpsk psk matlab,BPSK和QPSK调制解调原理及MATLAB程序资料
- 云服务商拿来主义或大限将至,Elastic 表示将变更开源许可协议并进行诉讼
- 视频帧率截取图像工具
- android matrix 亮度,Android ColorMatrix 亮度矩阵 对比度矩阵 黑白矩阵
- 银河麒麟高级服务器操作系统 V10 版本安装教程
- (转)走进全球CTA领导者:元盛资本(Winton CapitalManagement)
- python证明冰雹猜想_如果冰雹猜想被证明了。那数学会有很大突破吗?
- Adobe Photoshop CS5.1 Extended 12.1中文特别版
- sort在c语言中的作用,c语言中sort的用法详解.docx
- 免编程让你零基础制作App
- 小球称重的解法整合 N个小球有一个坏球,最少几次能找出坏球
- wkwebview替换uiwebview_使用WKWebView替换UIWebView
- 数据库优化:表的优化
- G470 deepin wifi无法开启
- python 中的np.zeros()和np.ones()函数
热门文章
- 安装uwsgi报错:error linking uWSGI解决方法
- 从零开始学Pytorch(十三)之梯度下降
- linux 网络命令 dns,[LN_03] Linux网络环境查看(网卡|路由|DNS|IP)、网络测试命令(端口探测|路由跟踪|抓包|ssh连接)...
- IaaS、PaaS和SaaS的区别
- micropython stm32f429_[MicroPython]STM32F407开发板驱动OLED液晶屏
- 求多个数的最小公倍数
- springboot filter_SpringBoot(二) :web综合开发
- json string 格式_python中json函数的用法
- cad怎么选择一个对象打散vba_CAD制图的二十四字秘诀!
- java 线程的join_多线程中join()