单例五种创建方式(下一篇:工厂模式)

什么是单例

保证一个类只有一个实例,并且提供一个访问该全局访问点

单例应用场景

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-单例五种创建方式相关推荐

  1. 单例对象会被jvm的gc时回收吗_【PHP设计模式】单例模式

    前言 设计模式是我们开发过程中的重中之重,所以今天小编就来学习设计模式中的单例模式. 单例模式 <?phpclass Singleton { /*** 定义一个静态变量保存已经实例化的对象* * ...

  2. JVM内功心法-GC垃圾回收之GC垃圾回收过程

    JVM内功心法-GC垃圾回收之GC垃圾回收算法 GC 全称garbagecollection,垃圾回收.JAVA 为了屏蔽操作系统和平台之间的差异.选择的是采用 java 虚拟机来运行 java 应用 ...

  3. JavaScript对象的几种创建方式?

    **` JavaScript对象的几种创建方式? `**

  4. 设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 ...

  5. 【JVM】GC垃圾回收(三)——零落成泥碾作尘,只有香如故

    [引子] 当世界上最后一个记得我的生命也忘记了我的时候,我该如何自处呢?我想我会最后看一眼我深爱的故乡,然后将占用这个世界的最后一缕精华也散去,让灵魂永归沉寂.GC垃圾回收机制也是如此,每一个最终消亡 ...

  6. JVM与GC垃圾回收(各种垃圾收集器,Jvm相关工具)

    1.JVM内存区域: 虚拟机栈,本地方法栈,程序计数器线程隔离,方法区,本地内存,直接内存,堆线程共享. ①.虚拟机栈:描述方法执行时的内存模型, 主要保存执行方法时的局部变量表.操作数栈.动态连接和 ...

  7. 详解JVM和GC垃圾回收

    文章目录 JVM架构图分析 Java虚拟机运行时数据区 对象的创建方式有几种? 创建对象的过程 对象的访问定位 垃圾回收机制 如何判断一个对象是否可以回收 垃圾回收算法都有哪些? 对象分代 垃圾回收器 ...

  8. 创建函数查找上级_一文秒懂JavaScript中对象的7种创建方式

    1.工厂模式 javascript 代码 工厂模式:能根据接受的参数来创建出一个person对象.也可以无数次的调用这个函数,每次都会返回一个包含3个属性和1个方法的对象. 工厂模式虽然解决了创建多个 ...

  9. axios post传递对象_axios的post传参时,将参数转为form表单格式

    import axios from 'axios'; import alert from './alert.js'; import Qs from 'qs' //引入qs 时axios的自带模块 le ...

最新文章

  1. 完美解决opencv-python中文路径解析问题
  2. 寻找阿姆斯特朗数c语言程序,C程序检查阿姆斯特朗数
  3. Hive SQL开窗函数详解
  4. 8.python之面相对象part.6(反射__call__,__setattr__,__delattr__,__getattr__)
  5. jQuery.fn.extend()方法
  6. qpsk psk matlab,BPSK和QPSK调制解调原理及MATLAB程序资料
  7. 云服务商拿来主义或大限将至,Elastic 表示将变更开源许可协议并进行诉讼
  8. 视频帧率截取图像工具
  9. android matrix 亮度,Android ColorMatrix 亮度矩阵 对比度矩阵 黑白矩阵
  10. 银河麒麟高级服务器操作系统 V10 版本安装教程
  11. (转)走进全球CTA领导者:元盛资本(Winton CapitalManagement)
  12. python证明冰雹猜想_如果冰雹猜想被证明了。那数学会有很大突破吗?
  13. Adobe Photoshop CS5.1 Extended 12.1中文特别版
  14. sort在c语言中的作用,c语言中sort的用法详解.docx
  15. 免编程让你零基础制作App
  16. 小球称重的解法整合 N个小球有一个坏球,最少几次能找出坏球
  17. wkwebview替换uiwebview_使用WKWebView替换UIWebView
  18. 数据库优化:表的优化
  19. G470 deepin wifi无法开启
  20. python 中的np.zeros()和np.ones()函数

热门文章

  1. 安装uwsgi报错:error linking uWSGI解决方法
  2. 从零开始学Pytorch(十三)之梯度下降
  3. linux 网络命令 dns,[LN_03] Linux网络环境查看(网卡|路由|DNS|IP)、网络测试命令(端口探测|路由跟踪|抓包|ssh连接)...
  4. IaaS、PaaS和SaaS的区别
  5. micropython stm32f429_[MicroPython]STM32F407开发板驱动OLED液晶屏
  6. 求多个数的最小公倍数
  7. springboot filter_SpringBoot(二) :web综合开发
  8. json string 格式_python中json函数的用法
  9. cad怎么选择一个对象打散vba_CAD制图的二十四字秘诀!
  10. java 线程的join_多线程中join()