赞
踩
什么是单例模式?单例模式就是采取一定的方法保证在整个系统中,只能存在一个对象实例。该类提供一个静态方法返回对象实例。
为什么要采用单例模式?
资源共享: 当你需要多个对象共享某些资源(如数据库连接池、线程池、缓存等)时,可以使用单例模式确保所有对象都使用同一个实例,避免资源的浪费和冲突。
全局访问点: 在某些情况下,需要全局访问一个对象,例如日志记录器、配置管理器等,这时可以使用单例模式确保在整个应用程序中只有一个实例,并且可以在任何地方方便地访问它。
控制实例数量: 单例模式可以限制类的实例化次数,确保只有一个实例存在。这在某些情况下是必要的,例如线程池中只需要有固定数量的线程实例。
懒加载: 在需要时才创建对象实例,延迟实例化。这可以节省资源,提高性能,尤其是当对象的初始化开销较大时。
保持一致性: 有些对象在系统中只应该有一个实例存在,例如系统配置信息或应用程序状态等。使用单例模式可以确保这些对象始终保持一致性。
采用单例模式的好处是什么?
- public class Singleton {
- // 静态常量,类加载时即创建
- private static final Singleton instance = new Singleton();
-
- // 私有构造函数,防止外部类实例化
- private Singleton() {}
-
- // 获取单例实例的静态方法
- public static Singleton getInstance() {
- return instance;
- }
-
- }
优点:写法简单,在类装载的时候完成了实例化,避免了线程安全的问题。
缺点:没有达到 懒加载的效果。如果系统中没有使用到这个实例,就会造成内存浪费。
- public class Singleton {
-
- private static Singleton instance;
-
- static{
- instance = new Singleton();
- }
-
- // 私有构造函数,防止外部类实例化
- private Singleton() {}
-
- // 获取单例实例的静态方法
- public static Singleton getInstance() {
- return instance;
- }
-
- }
优缺点同上,只是改变了代码方式。
- public class Singleton {
- // 私有静态变量,初始值为 null
- private static Singleton instance;
-
- // 私有构造函数,防止外部类实例化
- private Singleton() {}
-
- // 获取单例实例的静态方法
- public static Singleton getInstance() {
- // 判断实例是否已经创建,如果未创建,则创建新实例
- if (instance == null) {
- instance = new Singleton();
- }
- return instance;
- }
-
- }
优点:起到了懒加载的作用
缺点:只能在单线程下去使用,在多线程环境下,可能存在两个线程同时进去了if语句造成创建多个实例。在开发过程中,禁止使用这种方式。
- public class Singleton {
- // 私有静态变量,初始值为 null
- private static Singleton instance;
-
- // 私有构造函数,防止外部类实例化
- private Singleton() {}
-
- // 获取单例实例的静态方法,使用synchronized关键字保证只有一个线程执行方法。
- public static synchronized Singleton getInstance() {
- // 判断实例是否已经创建,如果未创建,则创建新实例
- if (instance == null) {
- instance = new Singleton();
- }
- return instance;
- }
-
- }
优点:解决了线程不安全问题
缺点:效率低下,每个线程在执行getInstance()方法时都需要等待其他线程释放锁,但在正常情况中,只需要有一个线程创建一次实例,其他线程直接获取返回值就可以了,因此在实际开发中仍然不推荐使用。
使用了volatile关键字,这个关键字修饰的变量对所有线程可见。关于该关键字的详细解释请看:多线程-并发编程、面试难点(线程合集)-CSDN博客
- public class Singleton {
- // 私有静态变量,初始值为 null
- private static volatile Singleton instance;
-
- // 私有构造函数,防止外部类实例化
- private Singleton() {}
-
- // 获取单例实例的静态方法
- public static Singleton getInstance() {
- // 双重判定解决线程安全问题,既保证了可以多线程访问,又保证了线程安全的问题。
- if (instance == null) {
- synchronized(singleton.class){
- if(instance == null){
- instance = new Singleton();
- }
- }
- }
- return instance;
- }
-
- }
优点:线程安全;懒加载;效率高;
缺点:无缺点,已经拉满了,开发中推荐使用!
这个实现原理是根据Java中类加载的顺序,在Singleton类加载时并不会加载静态内部类,而是只有在第一次调用的时候才会加载,借助这个类加载机制我们可以实现懒加载的单例。
- public class Singleton {
-
- // 私有构造函数,防止外部类实例化
- private Singleton() {}
-
- //使用静态内部类完成懒汉式单例
- private static class SingletonInstance{
- private static final Singleton INSTANCE = new Singleton();
- }
-
- // 获取单例实例的静态方法
- public static Singleton getInstance() {
-
- return SingletonInstance.INSTANCE;
- }
-
- }
- public enum Singleton {
- INSTANCE;
-
- // 枚举方法
- public void doSomething() {
- System.out.println("Singleton instance is doing something.");
- }
-
- }
-
线程安全: 枚举类型在 Java 中是线程安全的,因此不需要额外的同步措施来保证线程安全性。
简洁明了: 使用枚举实现单例模式代码简洁清晰,不需要手动编写单例模式的实现逻辑。
序列化安全: 枚举类型默认实现了 Serializable
接口,并且在反序列化时保证只会创建一个实例,因此可以保证序列化和反序列化的安全性。
防止反射攻击: 枚举类型的实现方式可以防止通过反射来创建多个实例的情况,确保单例的唯一性。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。