Java23种设计模式-创建型模式之单例模式

news/2024/9/22 15:41:28/

单例模式(Singleton Pattern):通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例),该类负责创建自己的对象,同时确保只有单个对象被创建。

1、单例类只能一个实例
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。

Java中两种构建方式:
懒汉式线程不安全:最基础的实现方式,线程上下文单例,不需要共享给所有线程,也不需要加synchronize之类的锁,以提高性能。这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作
懒汉式线程安全加上synchronize之类保证线程安全的基础上的懒汉模式,相对性能很低,大部分时间并不需要同步饿汉方式。指全局的单例实例在类装载时构建。
饿汉式:这种方式比较常用,但容易产生垃圾对象。优点:没有加锁,执行效率会提高。缺点:类加载时就初始化,浪费内存。基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果
双检锁/双重校验锁(DCL,即 double-checked locking):在懒汉式基础上利用synchronize关键字和volatile关键字确保第一次创建时没有线程间竞争而产生多个实例,仅第一次创建时同步,性能相对较高。
登记式/静态内部类:作为创建类的全局属性存在,创建类被装载时创建。
枚举:java中枚举类本身也是一种单例模式

应用场景包括需要控制实例数量的类,如数据库连接池配置管理日志记录等。单例模式的主要优点包括防止多次实例化节省资源提供全局访问点以及减少全局状态的复杂性。然而,它也有一些缺点,比如可能导致代码难以测试和维护,以及在多线程环境中可能存在线程安全问题

单例模式的实现通常包括将构造方法设置为私有,以防止外部代码创建实例。它还可能包括一个私有的静态实例成员以及一个公共的静态方法用于获取这个实例。此外,双重检查锁定(double-checked locking)是一种常用的实现线程安全单例的方法。

示例

//懒汉式,线程不安全
public class Singleton {private static Singleton instance;private Singleton(){}public static Singleton getInstance(){if (instance==null){instance=new Singleton();}return instance;}
}
//懒汉式 线程安全
public class Singleton {private static Singleton instance;public Singleton() {}public static synchronized Singleton getInstance(){if (instance==null){instance=new Singleton();}return instance;}
}
//饿汉式 线程安全
public class Singleton {private static Singleton instance=new Singleton();public Singleton() {}public static Singleton getInstance(){return instance;}
}
//双检锁/双重校验锁(DCL,即 double-checked locking)
public class Singleton {private volatile static Singleton singleton;public Singleton() {}public static Singleton getSingleton(){if (singleton==null){synchronized (Singleton.class){if (singleton==null){singleton=new Singleton();}}}return singleton;}
}//登记式/静态内部类
public class Singleton {private static class SingletonHolder{private static final Singleton INSTANCE=new Singleton();}public Singleton() {}public static final Singleton getInstance(){return SingletonHolder.INSTANCE;}
}
//枚举
public enum Singleton {INSTANCE;public void test(){System.out.println("hi~");}
}
//CAS「AtomicReference」(线程安全)
public class Singleton {private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>();private Singleton() {}public static final Singleton getInstance() {for (; ; ) {Singleton instance = INSTANCE.get();if (null != instance) return instance;INSTANCE.compareAndSet(null, new Singleton());return INSTANCE.get();}}public static void main(String[] args) {System.out.println(Singleton.getInstance()); System.out.println(Singleton.getInstance()); }
}

一般情况下,不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式

增加:CAS「AtomicReference」(线程安全)
java并发库提供了很多原子类来支持并发访问的数据安全性;AtomicInteger、AtomicBoolean、AtomicLong、AtomicReference。
AtomicReference 可以封装引用一个V实例,支持并发访问如上的单例方式就是使用了这样的一个特点。
使用CAS的好处就是不需要使用传统的加锁方式保证线程安全,而是依赖于CAS的忙等算法,依赖于底层硬件的实现,来保证线程安全。相对于其他锁的实现没有线程的切换和阻塞也就没有了额外的开销,并且可以支持较大的并发性。
当然CAS也有一个缺点就是忙等,如果一直没有获取到将会处于死循环中。


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

相关文章

【算法刷题 | 贪心算法04】4.26(跳跃游戏、跳跃游戏||)

文章目录 6.跳跃游戏6.1题目6.2解法&#xff1a;贪心6.2.1贪心思路6.2.2代码实现 7.跳跃游戏||7.1题目7.2解法&#xff1a;贪心7.2.1贪心思路7.2.2代码实现 6.跳跃游戏 6.1题目 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你…

Hadoop之路---伪分布式环境搭建

hadoop更适合在liunx环境下运行&#xff0c;会节省后期很多麻烦&#xff0c;而用虚拟器就太占主机内存了&#xff0c;因此后面我们将把hadoop安装到wsl后进行学习,后续学习的环境是Ubuntu-16.04 &#xff08;windows上如何安装wsl&#xff09; 千万强调&#xff0c;创建完hado…

【蓝桥杯2024真题】好数

试题C: 好数 时间限制: 1.0s 内存限制: 256.0MB 本题总分&#xff1a;10分 【问题描述】 一个整数如果按从低位到高位的顺序&#xff0c;奇数位&#xff08;个位、百位、万位&#xff09;上 的数字是奇数&#xff0c;偶数位&#xff08;十位、千位、十万位&#xff09;上的数…

中国股市:能赚钱的只有一种人

股市投资是一场马拉松&#xff0c;不是百米赛&#xff0c;你不能急于求成&#xff0c;更不能投机取巧&#xff01;短线是银&#xff0c;长线是金。 真正的投资家&#xff0c;是能看准股市的长期趋向&#xff0c;掌握先机&#xff0c;长期等待的人。只图短利而没有长远眼光的人…

Eagle for Mac:强大的图片管理工具

Eagle for Mac是一款专为Mac用户设计的图片管理工具&#xff0c;旨在帮助用户更高效、有序地管理和查找图片资源。 Eagle for Mac v1.9.2中文版下载 Eagle支持多种图片格式&#xff0c;包括JPG、PNG、GIF、SVG、PSD、AI等&#xff0c;无论是矢量图还是位图&#xff0c;都能以清…

面试:finalize

一、概述 将资源释放和清理放在finalize方法中非常不好&#xff0c;非常影响性能&#xff0c;严重时甚至会引起OOM&#xff08;Out Of Memory&#xff09;&#xff0c;从Java9开始就被标注为Deprecated&#xff0c;不建议被使用了。 二、两个重要的队列 1、unfinalized 队列 当…

Vue3 el-dialog 二次封装踩坑实录(v-model moduleValue 不触发)

如果你封装了一个el-dialog的子组件&#xff0c;想通过父组件v-model的形式调用&#xff0c;切记不能使用v-model&#xff0c;要使用 v-model:[你的参数]&#xff0c;例如 v-model:visible <template><el-dialogv-model"dialogVisibale":title"title&…

MySQL个人复习总结

最近想把MySQL的知识点再过一遍,带着自己的理解使用简短的话把一些问题总结一下,尤其是开发中和面试中的高频问题,基础知识点可以参考之前写的如下几篇博客,这篇不再赘述,阅读顺序由浅入深依次递进。 一、MySQL 概述 数据库&表操作 数据增删改; 二、MySQL 单表查询 …