单例模式java

news/2025/2/12 17:03:00/

下面是从一个不单例的代码逐步优化成单例的代码的过程。

1、两个类的关系为依赖关系

在一个类A的普通方法中new目标对象,多次执行方法,会创建多个目标对象。

//todo

2、两个类的关系由依赖变关联

扩大目标对象的作用域到普通方法外,在类A的范围内声明一个目标对象,在普通方法中使用目标对象前判断是否已经实例化,如果没有再实例化,否则直接使用。如果有多个类A对象,也会创建多个目标对象。此时目标对象还不是全局单例。

//todo

3、构造函数创建对象

接下来还怎么扩大作用域范围呢?把目标对象声明到哪里,在使用的时候能拿到唯一的实例呢?已经把目标对象的声明由调用方类A的方法内扩大到了它的类内,如果再往其他类C中实例化,在类A中使用,一来不合适,二来new多个类C,同样会有多个目标对象。所以放在调用方类的范围内实例化不能满足需求了。那放在目标对象类本身呢?一个类new不new对象,由它自己说了算。可以,把构造函数变私有,其他类不能去实例化它,只有它自己可以实例化,当不存在实例时再去创建。接下来再提供一个静态公有方法返回它的实例。所有其他类都通过静态公有方法获得目标对象。

//todo

4、多线程单例

多线程时如何保证单例呢?把获取单例对象的静态方法加锁,保证同一时刻只能有一个线程获取实例对象。这样足够了吧?还不行?获取对象会影响性能?还能怎么办?把锁粒度再小一点?

//todo

5、双重锁-懒汉式

锁粒度再小,由锁方法到锁对象?锁方法里的一个分支的代码,锁判断对象是否为创建,未创建则创建的代码。

给Singleton.class加synchronized锁,不太理解是什么意思?

instance属性加上volatile是什么意思?

//todo

以上是双重锁定方式,保证多线程时也单例,称为懒汉式加载

6、饿汉式

下面是饿汉式加载,上来就给静态的Singleton变量实例化,获取实例的方法直接返回此实例。

//todo

在Java中,单例模式的演变过程如下:

1. 1、简单单例模式:

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

2. 2、考虑多线程,使用同步方法:

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

3. 3、考虑性能,使用同步代码块:

public class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();} }}return instance;}
}

4. 4、进一步提高性能,使用双检查锁定:

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

5. 5、使用枚举实现单例:

public enum Singleton {INSTANCE;public void doSomething() {...}
}

这个是Java中单例模式的演变过程,从简单模式考虑多线程性能问题,最终使用枚举实现一个线程安全的单例。


http://www.ppmy.cn/news/575741.html

相关文章

Scipy之傅里叶和DCT

SciPy提供fftpack模块,可让用户计算快速傅立叶变换。 一维离散傅立叶变换 长度为N的序列x [n]的FFT y [k]由fft()计算,逆变换使用ifft()计算。 import numpy as np from scipy.fftpack import fft#快速傅里叶变换 def test01():x np.array([1.0, 2.0…

java魔界战记魔女_魔界战记风格RPG《魔女传说》最新公开!

主要人物介绍: 莉德露: 目前还在魔法学校里上学的见习魔女,拥有着强气而且不福输的性格。总是想着自己拥有魔女的才能,而对学校里学的东西很没兴趣,总想着该怎么去获得更强大的魔法。 路五: 沉眠于棺材里的…

魔界战记修复服务器,《魔界战记6》评测:突破天际的刷刷刷

全程自动挑战强敌 作为一款真正意义上的“刷子”游戏,如果一直让玩家去手动进行枯燥无味的操作,那势必会让玩家对于游戏的评价大打折扣,官方当然也考虑到了这一点,在游戏中贴心地加入了自动战斗系统。 这自动战斗功能依靠了本作新…

FC 电梯大战 金手指

在网上找了一圈没找到,自己探索了一下 1. 0590-01-03:人数不变

海能达 面试

自我介绍 EL和JSTL区别 项目中分页怎么做的 如何在不登录的情况下将商品添加到购物车 你的项目为什么用JSP 而不用别的 商品热度怎么做 SSH框架自己搭建 Hibernate怎么建立多对多的关系映射 SSH全部jar包都有哪些 都有什么用 Spring官方看过没有 里面都有哪些技术 Spring全家桶…

可达与不可达

可达:创建一个对象,系统中依然存在引用指向该对象,该对象是可达的 不可达:比如 class b new class(); bnull; 那在堆上分配的内存上的数据 就无法访问到了. 就是不可达对象.

海能达一面

海能达 自我介绍组件通信es6新特性跨域解决方案vdom与diff简单讲讲 总结 互相没有开视频,简单的回答了几个问题,大概15分钟就结束了。整体感觉面的还可以。

PDCA与PDSA哪一个比较优胜?

在医院质量管理工具中, PDCA循环与PDSA循环经常被混淆。从字母本身的含义,PDCA代表Plan-Do-Check-Act,PDSA代表Plan-Do-Study-Act。对于某些人来说,从“检查”(Check)到“学习”(Study&#xff…