单例模式的几种实现方式及其优缺点
创作时间:
作者:
@小白创作中心
单例模式的几种实现方式及其优缺点
引用
CSDN
1.
https://blog.csdn.net/wy02_/article/details/145202444
单例模式是Java编程中常用的设计模式之一,其核心目标是保证一个类只有一个实例,并提供一个全局访问点。本文将详细介绍单例模式的几种实现方式,包括饿汉式、懒汉式、双重检测锁、静态内部类和枚举单例,并讨论如何保证线程安全以及反射对单例模式的影响。
单例模式
作用:单例模式的核心是保证一个类只有一个实例,并且提供一个访问实例的全局访问点。
实现方式 优缺点
- 饿汉式:线程安全,调用效率高,但是不能延迟加载
- 懒汉式:线程安全,调用效率不高,能延迟加载
- 双重检测锁:在懒汉式的基础上解决并发问题
- 静态内部类:线程安全,资源利用率高,可以延时加载
- 枚举单例:线程安全,调用效率高,但是不能延迟加载
饿汉式
在类加载的时候立即实例化对象,实现的步骤是先私有化构造方法,对外提供唯一的静态入口方法
public class SingletonInstance1 {
private byte[] b1 = new byte[1024*1024];
private byte[] b2 = new byte[1024*1024];
private byte[] b3 = new byte[1024*1024];
// 声明此类型的变量,并实例化,当该类被加载的时候就完成了实例化并保存在了内存中
private final static SingletonInstance1 instance = new SingletonInstance1();
// 私有化所有的构造方法,防止直接通过new关键字实例化
private SingletonInstance1(){}
// 对外提供一个获取实例的静态方法
public static SingletonInstance1 getInstance(){
return instance;
}
}
在类加载时直接创建对象可能会造成空间的浪费
懒汉式
public class SingletonInstance2 {
// 声明此类型的变量,但没有实例化
private static SingletonInstance2 instance = null;
// 私有化所有的构造方法,防止直接通过new关键字实例化
private SingletonInstance2(){}
// 对外提供一个获取实例的静态方法
public static SingletonInstance2 getInstance(){
if(instance == null){
// 当instance不为空的时候才实例化
instance = new SingletonInstance2();
}
return instance;
}
}
外部调用getInstance()方法时才会创建对象(判断对象是否存在),但是不能保证多线程并发的情况下的线程安全,所以就出现了双重检测锁模式
双重检测锁模式
public class SingletonInstance3 {
// 声明此类型的变量,但没有实例化,防止指令重排
private volatile static SingletonInstance3 instance;
// 私有化所有的构造方法,防止直接通过new关键字实例化
private SingletonInstance3(){}
// 对外提供一个获取实例的静态方法
public static SingletonInstance3 getInstance(){
if(instance == null){
synchronized (SingletonInstance3.class){
if(instance == null){
// 当instance不为空的时候才实例化
instance = new SingletonInstance3();
/*
1.分配内存空间
2.执行构造法法,初始化对象
3.把这个对象指向这个空间
如果不加volatile 会执行重排序 1 3 2
*/
}
}
}
return instance;
}
}
静态内部类
public class SingletonInstance4 {
// 静态内部类
public static class SingletonClassInstance{
// 声明外部类型的静态常量
public static final SingletonInstance4 instance = new SingletonInstance4();
}
// 私有化构造方法
private SingletonInstance4(){}
// 对外提供的唯一获取实例的方法
public static SingletonInstance4 getInstance(){
return SingletonClassInstance.instance;
}
}
枚举
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance(){
return INSTANCE;
}
}
如何保证线程安全
推荐使用静态内部类或者双重检测锁配合volatile使用
反射破坏单例模式
代码如下
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class LazyMan {
private static boolean jiamibiaozhi = false; // 加密标志位
// 私有化所有的构造方法,防止直接通过new关键字实例化
private LazyMan(){
synchronized (LazyMan.class){
if(!jiamibiaozhi){ // 防止反射破坏单例
jiamibiaozhi = true;
}else {
throw new RuntimeException("不能试图使用反射破坏异常");
}
}
System.out.println(Thread.currentThread().getName() +"LazyMan");
}
// 声明此类型的变量,但没有实例化, volatile防止指令重排
private volatile static LazyMan instance;
// 对外提供一个获取实例的静态方法
public static LazyMan getInstance(){
if(instance == null){
synchronized (LazyMan.class){
if(instance == null){
// 当instance不为空的时候才实例化
instance = new LazyMan();
/*
1.分配内存空间
2.执行构造法法,初始化对象
3.把这个对象指向这个空间
如果不加volatile 会执行重排序 1 3 2
*/
}
}
}
return instance;
}
// 反射破环单列
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// LazyMan lazyMan = LazyMan.getInstance();
Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null); // 获取空参构造器
declaredConstructor.setAccessible(true); // 暴力反射,设置权限,无视私有构造器
LazyMan lazyMan1 = declaredConstructor.newInstance(); // 通过空参构造器创建对象
LazyMan lazyMan2 = declaredConstructor.newInstance();
System.out.println(lazyMan1);
System.out.println(lazyMan2);
}
}
反射不能破坏枚举,见源码
热门推荐
如何基于“一个设定”去推演构建一个底层逻辑自洽的“科技流修真世界”?
企业如何促进员工的自律
AI绘画是一种新型艺术形式
AI助力内容生产:提升效率新策略-利用人工智能优化内容创作与生产效率的实用指南
最高月薪5万元!重庆“智能+”岗位真香→
最高月薪5万元!重庆“智能+”岗位招聘火热
如何设计合理的房间布局?这种设计需要考虑哪些因素?
推荐10部高分拳击电影,励志热血,激爽炸裂!
围棋入门基本知识图解(从零开始学围棋)
武汉艺术生语文文化课:如何找到合适的提升方法?
“友谊的小船说翻就翻”:从英文单词到网络流行语的演变历程
福建惠安辋川:“侯卿十八游大鼓”传统民俗活动盛大举行
伊斯兰复兴运动的历史概况
江苏宜居之城,花落谁家?这三个城市是你认可的答案吗?
天庭中的神仙是怎么排名的?排在第一位的是谁?答案来了!
有固定收入如何合理规划抚养费支出?
值神什么意思?详解农历十二神煞吉凶表
西游记里孙行者、猪刚鬣,沙和尚,是他们的本名吗?
开源大模型部署及推理所需显卡成本必读:也看大模型参数与显卡大小的大致映射策略
五大垂钓要领,巧钓溪石斑鱼
激光切割机使用的安全注意事项
“乐不思蜀”的刘禅:弱势中知自励,成长中知自强,绝望中知自省
自我疲劳缓解策略大揭秘
孙悟空的修行之路,能看懂的寥寥无几!
打破沟通壁垒:5个实用步骤提升你的交流效率
限制条款是什么?类型、法律效力及制定指南
五绝与七绝的格律与创作:结构、平仄、韵脚与拗救的艺术
“必须得学会跟这帮人说不”|你的过度礼貌,是对自己的不负责
【调查】日本博士生质量堪忧,研究学者和管理人员危机感增加
探秘“正大光明”:清朝皇帝的权力象征与治国理念